Table of Contents
1. Brief introduction
2. Configuration project
Open CubeMX, configure clock, debugging interface, project name, directory, etc.
Configure iic
Configure the serial port to display information
3. Hardware connection
4. Code writing
1. Write a byte randomly
test code
The waveform is as follows
Code writing
2. Continuous writing
code show as below
3. Random reading
test code
The waveform is as follows
Code writing
4. Continuous reading
code show as below
5. Effect display
5. Driver Appendix
AT24C256.h
AT24C256.c
1. Brief introduction
EEPROM (Electrically Erasable Programmable read only memory) refers to electrically erasable programmable read-only memory. It is a memory chip that does not lose data after power failure. EEPROM can be erased and reprogrammed on a computer or special device. Generally used in plug and play.
The module used by the author is AT24C256, with a storage capacity of 256Kb or 32KB (32K bytes). The schematic diagram of the module is as follows
Pin name | Function |
A0-A1 (A2 is actually an NC foot, the principle picture is wrong) | Device address input |
SDA (in the schematic diagram DATA foot) | Serial data |
SCL | Clock |
WP (HOLD foot in the schematic) | Write protection (high level is valid) |
VCC | Connect to high level (1.8-5.5V wide voltage) |
GND | Ground |
The driver protocol is IIC. Consider enabling hardware IIC for communication. The author chose to use IIC2.
2. Configuration Project
Open CubeMX, configure clock, debugging interface, project name, directory, etc.
Configuration iic
Configure the serial port to display information
3. Hardware connection
As configured in the previous step, connect the module to the microcontroller as follows
PB10—->SCL
PB11—->SDA
VCC—->3V3
GND—->GND
4. Code Writing
1. Write a byte randomly
First send the device address or read and write instructions, then send the address to be written (occupies 2 bytes), then send the written byte, and then send the stop bit.
Since A0 and A1 are both low level, that is, 0, then the device address is 0x50(0101 0000)
This is writing, R/W is 0, after combination it is 0xA0
Test code
That is, write data “1” to the memory address of AT24C256 0. It should be noted that AT24C256 needs to wait 5~10ms to write data, and a delay must be added
The waveform is as follows
Code Writing
void AT24C256_WriteByte(uint16_t addr,uint8_t dat) { HAL_I2C_Mem_Write( & amp;hi2c2,AT24C256_ADDR_WRITE,addr,AT24C256_ADDR_LEN, & amp;dat,1,0xffff); HAL_Delay(AT24C256_WAIT_TIME_UINT); }
2. Continuous writing
Continuous writing is similar to random writing, except that if the number of writes at one time exceeds the number of bytes on a page or the address is counted to the end of a page, it will return to the beginning of the page to overwrite the number written without The page will turn automatically, this is what needs to be dealt with.
The code is as follows
/* AT24C256 has 256K bits, that is, 32KB, 32k bytes, and the addressing space is 0~0x7FFF. Divided into two bytes, address 1 is 0~0x7F, address AT24C256_ADDR_LEN is 0~0xFF One page has 64 bytes and is divided into 512 pages */ void AT24C256_WriteMultiByte(uint16_t addr,uint8_t* dat,uint16_t n) { uint16_t i = 0; uint16_t cnt = 0; //Write byte count uint16_t head; uint16_t left; uint16_t tail; \t if((n + addr)/AT24C256_PAGE_SIZE == addr/AT24C256_PAGE_SIZE) //If on the same page { HAL_I2C_Mem_Write( & amp;hi2c2, AT24C256_ADDR_WRITE, addr, AT24C256_ADDR_LEN, dat, n, 0xFFFF); HAL_Delay(AT24C256_WAIT_TIME_UINT*n); } else { head = (addr / AT24C256_PAGE_SIZE + 1) * AT24C256_PAGE_SIZE - addr; //The number of bytes remaining to be written in the starting page left = n - head; //Number of bytes remaining after excluding the start page tail=left-left/AT24C256_PAGE_SIZE*AT24C256_PAGE_SIZE; //Number of bytes to be written on the last page HAL_I2C_Mem_Write( & amp;hi2c2, AT24C256_ADDR_WRITE,addr,AT24C256_ADDR_LEN,dat,head,0xffff); HAL_Delay(AT24C256_WAIT_TIME_UINT*head); for(i=0;i<left/AT24C256_PAGE_SIZE;i + + ) { HAL_I2C_Mem_Write( & amp;hi2c2, AT24C256_ADDR_WRITE, addr + head + i*AT24C256_PAGE_SIZE,\ AT24C256_ADDR_LEN, dat + head + i*AT24C256_PAGE_SIZE,AT24C256_PAGE_SIZE, 0xFFFF); HAL_Delay(AT24C256_WAIT_TIME_UINT*AT24C256_PAGE_SIZE); } HAL_I2C_Mem_Write( & amp;hi2c2, AT24C256_ADDR_WRITE,addr + head + i*AT24C256_PAGE_SIZE,AT24C256_ADDR_LEN,\ dat + head + i*AT24C256_PAGE_SIZE,tail,0xffff); HAL_Delay(AT24C256_WAIT_TIME_UINT*tail); } }
3. Random reading
First send a fake write action, locate the address to the place to be read, and then send the read command. At this time, the module will clock out the data one by one
Test code
The waveform is as follows
Code writing
uint8_t AT24C256_ReadByte(uint16_t addr) { uint8_t p; HAL_I2C_Mem_Read( & amp;hi2c2,AT24C256_ADDR_READ,addr,AT24C256_ADDR_LEN, & amp;p,1,0xffff); return p; }
Four. Continuous Reading
Since the address will automatically increase during continuous reading and writing, and the page will turn, there is no need to worry about repeated reading. As long as you do not read addresses larger than the maximum address range, there is generally no problem (after testing by the author, if you read the 0x8000 address value, the value obtained is the value at 0x0000), and there is no need to wait to read the data, which is very good
The code is as follows
/* Continuously read bytes, the parameters are the starting reading address, the address used to store data, and the number to be read. */ void AT24C256_ReadMultiByte(uint16_t addr,uint8_t* dat,uint16_t n) { if(addr + n<0x8000) HAL_I2C_Mem_Read( & amp;hi2c2,AT24C256_ADDR_READ,addr,AT24C256_ADDR_LEN,dat,n,0xffff); }
5. Effect display
The main function main.cmain code is as follows
#include "main.h" #include "i2c.h" #include "tim.h" #include "usart.h" #include "gpio.h" /* Private includes -------------------------------------------------- ----------*/ /* USER CODE BEGIN Includes */ #include "AT24C256.h" #include "stdio.h" #include "stdlib.h" /* USER CODE END Includes */ /* Private typedef ----------------------------------------------- -------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define -------------------------------------------------- ---------------*/ /* USER CODE BEGIN PD */ #define TEST_BUFFER_LEN 1024 /* USER CODE END PD */ /* Private macro ----------------------------------------------- ---------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables -------------------------------------------------- -----------*/ /* USER CODE BEGIN PV */ uint16_t x; uint8_t buffer[TEST_BUFFER_LEN]; uint8_t b[TEST_BUFFER_LEN]; /* USER CODE END PV */ /* Private function prototypes ------------------------------------------------ --*/ void SystemClock_Config(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /*Private user code--------------------------------------------- ----------*/ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration------------------------------------------------- ----------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_I2C1_Init(); MX_I2C2_Init(); MX_TIM2_Init(); MX_USART1_UART_Init(); /* USER CODE BEGIN 2 */ for(x=0;x<TEST_BUFFER_LEN;x + + ) { *(buffer + x)=x%6; } printf("start\r\\ "); AT24C256_WriteMultiByte(0x0,buffer,TEST_BUFFER_LEN); printf("end\r\\ "); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { AT24C256_ReadMultiByte(0,b,TEST_BUFFER_LEN); for(uint16_t i=0;i<TEST_BUFFER_LEN;i + + ) { x=AT24C256_ReadByte(i); printf("addr:%d\t-->:%d\r\\ ",i,b[i]); } printf("\r\\ \r\\ \r\\ "); HAL_Delay(1000); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ }
5. Driver Appendix
AT24C256.h
#ifndef AT24C256_H #define AT24C256_H #include "main.h" #define AT24C256_ADDR_LEN 2 #define AT24C256_ADDR_WRITE 0xA0 #define AT24C256_ADDR_READ 0xA1 #define AT24C256_PAGE_SIZE 64 #define AT24C256_WAIT_TIME_UINT 2 #define AT24C256_MEM_LEN 0x8000 void AT24C256_WriteByte(uint16_t add,uint8_t dat); uint8_t AT24C256_ReadByte(uint16_t add); void AT24C256_WriteMultiByte(uint16_t add,uint8_t* dat,uint16_t n); void AT24C256_Fill(uint8_t fill); void AT24C256_ReadMultiByte(uint16_t addr,uint8_t* dat,uint16_t n); #endif
AT24C256.c
#include "i2c.h" #include "AT24C256.h" #include "string.h" uint8_t erase[512]; void AT24C256_WriteByte(uint16_t addr,uint8_t dat) { HAL_I2C_Mem_Write( & amp;hi2c2,AT24C256_ADDR_WRITE,addr,AT24C256_ADDR_LEN, & amp;dat,1,0xffff); HAL_Delay(AT24C256_WAIT_TIME_UINT); } /* AT24C256 has 256K bits, that is, 32KB, 32k bytes, and the addressing space is 0~0x7FFF. Divided into two bytes, address 1 is 0~0x7F, address 2 is 0~0xFF One page has 64 bytes and is divided into 512 pages */ void AT24C256_WriteMultiByte(uint16_t addr,uint8_t* dat,uint16_t n) { uint16_t i = 0; uint16_t cnt = 0; //Write byte count uint16_t head; uint16_t left; uint16_t tail; \t if((n + addr)/AT24C256_PAGE_SIZE == addr/AT24C256_PAGE_SIZE) //If on the same page { HAL_I2C_Mem_Write( & amp;hi2c2, AT24C256_ADDR_WRITE, addr, AT24C256_ADDR_LEN, dat, n, 0xFFFF); HAL_Delay(AT24C256_WAIT_TIME_UINT*n); } else { head = (addr / AT24C256_PAGE_SIZE + 1) * AT24C256_PAGE_SIZE - addr; //The number of bytes remaining to be written in the starting page left = n - head; //Number of bytes remaining after excluding the start page tail=left-left/AT24C256_PAGE_SIZE*AT24C256_PAGE_SIZE; //Number of bytes to be written on the last page HAL_I2C_Mem_Write( & amp;hi2c2, AT24C256_ADDR_WRITE,addr,AT24C256_ADDR_LEN,dat,head,0xffff); HAL_Delay(AT24C256_WAIT_TIME_UINT*head); for(i=0;i