STM32 entry development: using IIC hardware timing to read and write AT24C08 (EEPROM)

STM32 entry development: using IIC hardware timing to read and write AT24C08 (EEPROM)

1. Environmental introduction

Programming software: keil5

Operating system: win10

MCU model: STM32F103ZET6

STM32 programming method: register development (convenient for program migration to other microcontrollers)

IIC bus:  STM32 itself supports IIC hardware timing. The previous article has introduced the use of IIC analog timing to read and write AT24C02. This article introduces the hardware IIC configuration method of STM32, and reads and writes AT24C08.

Article address: xiaolong.blog.csdn.net/article/det...

Analog timing is more convenient to transplant to other single-chip microcomputers, with higher versatility, regardless of MCU; hardware timing efficiency is higher, each MCU configuration method is different, and it depends on the hardware itself.

Device model: using AT24C08 EEPROM memory chip

The complete project source code download address, download it to compile and run the test (including simulated IIC timing, STM32 hardware IIC timing to drive AT24C02 and AT24C08 respectively):  download.csdn.net/download/xi...

2. AT24C08 memory chip introduction

2.1 Introduction to chip features

AT24C08 is a serial CMOS type EEPROM memory chip. The AT24C0x series includes specific chip models such as AT24C01, AT24C02, AT24C04, AT24C08, and AT24C16 .

Their capacities are: 1K (128 x 8), 2K (256 x 8), 8K (1024 x 8), 16K (2048 x 8), where 8 means 8 bits (bit)

Their pin functions and packaging features are as follows:

Chip function description:

The AT24C08 series supports I2C, the bus data transfer protocol I2C. The bus protocol stipulates that any device that transfers data to the bus is used as a transmitter. Any device that receives data from the bus is a receiver; data transmission is controlled by the master device that generates the serial clock and all start and stop signals. Both the master device and the slave device can be used as transmitters or receivers, but the master device controls the mode of transmitting data (sending or receiving).

Introduction of chip characteristics:

1. Low voltage and standard voltage operation
-2.7 (VCC=2.7V to 5.5V)
-1.8 (VCC=1.8V to 5.5V)

2. Two-wire serial interface (SDA, SCL)

3. There is a write protection pin for hardware data protection

4. Self-timed write cycle (5 milliseconds to 10 milliseconds), because there is a page buffer inside, after writing data to AT24C0x, you need to wait for AT24C0x to write the buffer data to the internal EEPROM area.

5. Data can be stored for up to 100 years

6. 1 million erase and write cycles

7. The high data transfer rate is 400KHz, the low speed 100KHZ is compatible with IIC bus. 100 kHz (1.8V) and 400 kHz (2.7V, 5V)

8. 8-byte page write buffer
The size of this buffer is related to the specific chip model: 8-byte pages (1K, 2K), 16-byte pages (4K, 8K, 16K)

2.2 Introduction of chip device address

Because the IIC protocol stipulates that each transfer of data is transmitted in 8 bytes, AT24C08 is 1024 bytes, and the address selection is different from AT24C02;

The standard address bit of the IIC device is 7 bits. In the above figure, 1010 of AT24C08 is a fixed value inside the chip, A2 is a hardware pin, and the level is determined by the hardware; P1 and P0 are space storage block selections, each storage block size is 256 bytes, and the addressing range is 0~ 255, AT24C08 is equivalent to the structure of 4 AT24C02; the last bit is the read/write bit (1 is read, 0 is write), the read and write bits are not counted in the address bits, but according to the sequence of IIC, before operating the device , You need to send a 7-bit address first, and then send a 1-bit read and write bit to start the operation of the chip. We are writing the simulation timing in order to write the for loop uniformly and send it by byte, so generally the 7 address bits are combined with 1 read and write bits are put together and combined into 1 byte, which is convenient for byte-by-byte transmission of data.

The schematic diagram of the AT24C08 on the development board I am using now looks like this:

Then the standard device addresses of this AT24C08 are:

The first area: 0x50 (hexadecimal), the corresponding binary is: 1010000

The second area: 0x51 (hexadecimal), the corresponding binary is: 1010001

The third area: 0x52 (hexadecimal), the corresponding binary is: 1010010

The fourth area: 0x53 (hexadecimal), the corresponding binary is: 1010011

If the read and write bits are combined, the device address of the read permission: 

The first area: 0xA1 (hexadecimal), the corresponding binary is: 10100001

The second area: 0xA3 (hexadecimal), the corresponding binary is: 10100011

The third area: 0xA5 (hexadecimal), the corresponding binary is: 10100101

The fourth area: 0xA7 (hexadecimal), the corresponding binary is: 10100111

If the read and write bits are combined, the device address of the write permission: 

The first area: 0xA0 (hexadecimal), the corresponding binary is: 10100000

The second area: 0xA2 (hexadecimal), the corresponding binary is: 10100010

The third area: 0xA4 (hexadecimal), the corresponding binary is: 10100100

The fourth area: 0xA6 (hexadecimal), the corresponding binary is: 10100110

2.3 The instruction flow (timing) of writing data by byte to AT24C08

** explain in detail:**

1. Send the start signal first

2. Sending device address (write permission)

3. Waiting for AT24C08 response, low level is active

4. Send the storage address. There is a total of 256 bytes of space inside the AT24C08. The addressing starts from 0 and the range is (0~255); sending this memory address is to tell the AT24C08 where to store the next data.

5. Waiting for AT24C08 response, low level is active

6. Send one byte of data, this data is the data you want to store in AT24C08.

7. Wait for AT24C08 response, low level is active

8. Send stop signal

 

2.3 The instruction flow of writing data by page to AT24C08 (timing)

explain in detail:

1. Send the start signal first

2. Sending device address (write permission)

3. Waiting for AT24C08 response, low level is active

4. Send the storage address. There is a total of 256 bytes of space inside the AT24C08. The addressing starts from 0 and the range is (0~255); sending this memory address is to tell the AT24C08 where to store the next data.

5. Waiting for AT24C08 response, low level is active

6. You can send 8 bytes of data cyclically. These data are the data you want to store in the AT24C08.

    The page buffer of AT24C08 is 16 bytes, and all the loops here can only send 16 bytes at most. The more bytes sent will overwrite the previous ones.

   Points to note: The addressing of this page buffer also starts from 0, for example: 0~15 counts as the first page, 16~32 counts as the second page...and so on. If the starting address of writing data is 3, then only 13 bytes can be written on this page; it does not mean that 16 bytes can be written in a loop from anywhere.

      Detailed process: The for loop is generally used in this program to achieve 

     (1). Send byte 1

     (2). Wait for AT24C08 response, low level is active

     (3). Send byte 2

     (4). Wait for AT24C08 response, low level is active

     .........

     Up to 8 times.   

7. Wait for AT24C08 response, low level is active

8. Send stop signal

2.4 Read arbitrary byte data from AT24C08 arbitrary address (timing)

AT24C08 supports current address reading, arbitrary address reading, the most commonly used is arbitrary address reading, because the address for reading data can be specified, which is more flexible. The above specified timing diagram is arbitrary address reading.

explain in detail:

1. Send the start signal first

2. Sending device address (write permission)

3. Waiting for AT24C08 response, low level is active

4. Send the memory address. There are 2048 bytes in AT24C08. The addressing starts from 0 and the range is (0~1024). Sending this memory address tells AT24C08 that the data at that address should be returned to the MCU next.

5. Waiting for AT24C08 response, low level is active

6. Resend the start signal (switch read and write mode)

7. Sending device address (read permission)

8. Wait for AT24C08 response, low level is active

9. Cyclic read data: Receive data returned by AT24C08.

   There is no byte limit for reading data, the first byte or the entire chip can be read continuously.

10. Send non-response (active high)

11. Send stop signal

3. IIC bus introduction

       2.1 Introduction to IIC bus

The I2C (Inter-Integrated Circuit) bus is a two-wire serial bus developed by PHILIPS, which is used to connect microcontrollers and their peripherals. It is a bus standard widely used in the field of microelectronics communication control. It has the advantages of fewer interface lines, simple control mode, small device packaging form, and higher communication speed.

The I2C protocol uses master/slave two-way communication. When the device sends data to the bus, it is defined as a transmitter, and when the device receives data, it is defined as a receiver. Both the master device and the slave device can work in receiving and sending states.

The I2C bus transfers information between the devices connected to the bus through the serial data (SDA) line and the serial clock (SCL) line. Each device has a unique address identification, and can be used as a transmitter or receiver (determined by the function of the device).

I2C has four working modes:
1. Host sending
2. Host receiving
3. Slave sending
4. Slave receiving

The I2C bus uses only two wires: serial data SDA (Serial Data) and serial clock SCL (Serial Clock).

The bus must be controlled by the host (usually a microcontroller). The host generates a serial clock (SCL) to control the direction of the bus, and generates start and stop conditions.

The data state on the SDA line can only be changed when SCL is low.

2.2 Device connection diagram on IIC bus

The I2C bus is very simple in physical connection, consisting of SDA (serial data line) and SCL (serial clock line) and pull-up resistors. The communication principle is to generate the signals required by the I2C bus protocol for data transmission by controlling the high and low timing of the SCL and SDA lines. When the bus is in idle state, these two lines are generally pulled high by the pull-up resistor connected above, and maintain a high level.

The pull-up resistance range is 4.7K~100K.

2.3 I2C bus characteristics

Each device on the I2C bus can be used as a master device or a slave device, and each slave device corresponds to a unique address (which can be learned from the data manual of the I2C device). The master and slave devices use this address to determine which device to communicate with. In normal applications, we use the CPU module with I2C bus interface as the master device, and all other devices connected to the bus as slave devices.

1. The number of devices
that can be attached to the bus The number of devices that can be attached to the I2C bus is limited by the bus's maximum capacitance of 400pF. If the devices of the same model are attached, it is also limited by the device address.
Generally, the I2C device address is a 7-bit address (there are also 10 bits), and the address is divided into two parts: the chip curing address (which is connected to the ground when the chip is produced, and which is connected to the power supply, which has been fixed), and the programmable address (leads out the IO port, which is determined by the hardware device) .
For example: A certain device has a 7-bit address. The upper 4 bits of 10101 xxx are fixed at the factory, and the lower 3 bits can be determined by the designer.
At least 8 devices of this kind can be connected to an I2C bus.
If all 7-bit addresses can be programmed, then in theory it can reach 128 devices, but in practice, so many devices will not be mounted.

2. Bus speed transmission speed:
I2C bus data transmission rate can reach 100kbit/s in standard mode, 400kbit/s in fast mode, and 3.4Mbit/s in high speed mode. The adjustment of the transmission rate is generally realized through the programmable clock of the I2C bus interface.

3. Bus data length The
two-way data transmission between the master device and the slave device on the I2C bus takes bytes (8 bits) as the unit.

 2.4 I2C bus protocol basic timing signal

Idle state: Both SCL and SDA remain high.

Start condition: When the bus is in the idle state, both SCL and SDA remain high. When SCL is high, the transition of SDA from high to low indicates that a starting condition is generated. After the initial condition is generated, the bus is in a busy state and is exclusively occupied by the master and slave devices of this data transfer, and other I2C devices cannot access the bus.

Stop condition: When SCL is high and SDA transitions from low to high, it means that a stop condition is generated.

Acknowledgment signal : the next clock signal after the completion of each byte transmission. During the high level of SCL, when SDA is low, it means an acknowledge signal.

Non-accepted signal: the next clock signal after the completion of each byte transmission. During the high level of SCL, when SDA is high, it means an acknowledge signal. The acknowledge signal or non-acknowledge signal is sent by the receiver, and the transmitter detects this signal (the transmitter, the receiver can be a slave device or a master device).

Note: The start and end signals are always generated by the master device.

 

2.5 Start signal and stop signal

The start signal is: when the clock line SCL is at a high level, the data line SDA changes from a high level to a low level. SCL=1; SDA=1; SDA=0;

The stop signal is: when the clock line SCL is at a low level, the data line SDA changes from a low level to a high level. SCL=1; SDA=0; SDA=1;

2.6 Response signal

The ninth bit of the data bit is an immediate response bit. The process of reading the response bit is the same as reading the data bit. Example: SCL=0;SCL=1;ACK=SDA; This ACK is the read response status.

2.7 Data bit transmission timing

According to the timing diagram, the data is stable when SCL is at a high level, and data is unstable when SCL is at a low level.

Then for writing a bit of data (STM32--->AT24C08): SCL=0; SDA=data; SCL=1; 

Then for reading one bit of data (STM32<-----AT24C08): SCL=0;SCL=1;data=SDA;  

  2.8 Bus timing

4. IIC bus timing code, AT24C08 read and write code

  When debugging IIC simulation timing, you can buy a 24M USB logic analyzer on Taobao. If there is a problem with the timing, you can quickly find the problem by analyzing the logic analyzer.

 

4.1 iic.c This is the complete code of IIC hardware timing of STM32

/* Function: Initialize the IIC bus Hardware connection: SCL---PB6 SDA---PB7 */ void IIC_Init ( void ) { /*1. Clock configuration*/ RCC->APB2ENR|= 1 << 3 ; //PB /*2. GPIO port mode configuration*/ GPIOB->CRL&= 0x00FFFFFF ; GPIOB->CRL| = 0xFF000000 ; //Multiplexed open-drain output GPIOB->ODR| = 0x3 << 6 ; /*3. GPIO port clock configuration (sequence cannot be wrong)*/ RCC->APB1ENR|= 1 << 21 ; //I2C1 clock RCC->APB1RSTR|= 1 << 21 ; //Enable reset clock RCC->APB1RSTR& =~( 1 << 21 ); //Turn off the reset clock /*4. Configure the core register of IIC*/ I2C1->CR2 = 0x24 << 0 ; //Configure the host frequency to 36MHZ I2C1->CCR| = 0x2D << 0 ; //Configure the host frequency to be 400KHZ I2C1->CR1 |= 1 << 0 ; //Open the IIC module /* CCR=Host clock frequency/2/IIC bus frequency 45=36MHZ/2/400KHZ ---0x2D */ } /* Function function: send start signal When the clock line is high, the data line changes from high to low */ void IIC_SendStart ( void ) { I2C1->CR1|= 1 << 8 ; //Generate the start signal while (!(I2C1->SR1& 1 << 0 )){} //Wait for the start signal to complete I2C1->SR1 = 0 ; //Clear Status bit } /* Function: stop signal When the clock line is high, the process of the data line from low to high */ void IIC_SendStop ( void ) { I2C1->CR1|= 1 << 9 ; } /* Function: Send address data */ void IIC_SendAddr (u8 addr) { u32 s1,s2; I2C1->DR=addr; //Send data while ( 1 ) { s1=I2C1->SR1; s2=I2C1->SR2; if (s1& 1 << 1 ) //Determine whether the address is successfully sent { break ; } } } /* Function function: send data */ void IIC_SendOneByte (u8 addr) { u32 s1,s2; I2C1->DR=addr; //Send data while ( 1 ) { s1=I2C1->SR1; s2=I2C1->SR2; if (s1& 1 << 2 ) //Judging whether the data has been sent successfully { break ; } } } /* Function: Receive a byte of data */ u8 IIC_RecvOneByte ( void ) { u8 data = 0 ; I2C1->CR1|= 1 << 10 ; //Enable response while (!(I2C1->SR1& 1 << 6 ))() //Waiting for data data=I2C1->DR; I2C1->CR1&=~( 1 << 10 ); //Close response enable return data; } Copy code

4.2 AT24C08.c This is the complete read and write code of AT24C08

* Function function: write a byte Function parameters: u8 addr data location ( 0 ~ 1023 ) u8 data data range ( 0 ~ 255 ) */ void AT24C08_WriteOneByte (u16 addr,u8 data) { u8 read_device_addr=AT24C08_READ_ADDR; u8 write_device_addr=AT24C08_WRITE_ADDR; if (addr< 256 * 1 ) //The first block { write_device_addr|= 0x0 << 1 ; read_device_addr|= 0x0 << 1 ; } else if (addr< 256 * 2 ) //The second block { write_device_addr|= 0x1 << 1 ; read_device_addr|= 0x1 << 1 ; } else if (addr< 256 * 3 ) //The third block { write_device_addr|= 0x2 << 1 ; read_device_addr|= 0x2 << 1 ; } else if (addr< 256 * 4 ) //The fourth block { write_device_addr|= 0x3 << 1 ; read_device_addr|= 0x3 << 1 ; } addr=addr% 256 ; //Get the address range IIC_SendStart (); //Start signal IIC_SendAddr (write_device_addr); //Send device address IIC_SendOneByte (addr); //Data storage address IIC_SendOneByte (data); //Send the data to be stored IIC_SendStop (); //Stop signal DelayMs ( 10 ); //Waiting to write } /* Function function: read a byte Function parameters: u8 addr data location (0~1023) Return value: the data read */ u8 AT24C08_ReadOneByte (u16 addr) { u8 data = 0 ; u8 read_device_addr=AT24C08_READ_ADDR; u8 write_device_addr=AT24C08_WRITE_ADDR; if (addr< 256 * 1 ) //The first block { write_device_addr|= 0x0 << 1 ; read_device_addr|= 0x0 << 1 ; } else if (addr< 256 * 2 ) //The second block { write_device_addr|= 0x1 << 1 ; read_device_addr|= 0x1 << 1 ; } else if (addr< 256 * 3 ) //The third block { write_device_addr|= 0x2 << 1 ; read_device_addr|= 0x2 << 1 ; } else if (addr< 256 * 4 ) //The fourth block { write_device_addr|= 0x3 << 1 ; read_device_addr|= 0x3 << 1 ; } addr=addr% 256 ; //Get the address range IIC_SendStart (); //Start signal IIC_SendAddr (write_device_addr); //Send device address IIC_SendOneByte (addr); //The address of the data to be read IIC_SendStart (); //Start signal IIC_SendAddr (read_device_addr); //Send device Address data = IIC_RecvOneByte (); //Read data IIC_SendStop (); //Stop signal return data; } /* Function: Read data of specified length from specified location Function parameters: u16 addr data location (0~1023) u16 len read length u8 *buffer stores the read data Return value: the data read */ void AT24C08_ReadByte (u16 addr,u16 len,u8 *buffer) { u16 i = 0 ; IIC_SendStart (); //Start signal IIC_SendAddr (AT24C08_WRITE_ADDR); //Send device address IIC_SendOneByte (addr); //The address of the data to be read IIC_SendStart (); //Start signal IIC_SendAddr (AT24C08_READ_ADDR) ; //Send device address for (i= 0 ;i<len;i++) { buffer[i]= IIC_RecvOneByte (); //Read data } IIC_SendStop (); //Stop signal } /* Function: AT24C08 page write function Function parameters: u16 addr write position (0~1023) u8 len Length of writing (16 bytes per page) u8 *buffer stores the read data */ void AT24C08_PageWrite (u16 addr,u16 len,u8 *buffer) { u16 i = 0 ; IIC_SendStart (); //Start signal IIC_SendAddr (AT24C08_WRITE_ADDR); //Send device address IIC_SendOneByte (addr); //Data storage address for (i = 0 ;i<len;i++) { IIC_SendOneByte (buffer[i]); //Send the data to be stored } IIC_SendStop (); //Stop signal DelayMs ( 10 ); //Waiting to write } /* Function: write data of specified length from specified location Function parameters: u16 addr data location (0~1023) u16 len length written u8 *buffer stores the data to be written Return value: the data read */ void AT24C08_WriteByte (u16 addr,u16 len,u8 *buffer) { u8 page_byte = 16 -addr% 16 ; //Get the number of bytes remaining in the current page if (page_byte>len) //Determine whether the remaining byte space of the current page is enough for writing { page_byte=len; //means that it can be written at one time } while ( 1 ) { AT24C08_PageWrite (addr,page_byte,buffer); //write a page if (page_byte==len) break ; //finished buffer+=page_byte; //pointer offset addr+=page_byte; //address offset len-=page_byte; //Get the remaining uncompleted length if (len> 16 )page_byte = 16 ; else page_byte=len; //can be written at once } } Copy code

 4.3 main.c This is the AT24C08 test code

# include "stm32f10x.h" # include "beep.h" # include "delay.h" # include "led.h" # include "key.h" # include "sys.h" # include "usart.h" # include <string.h> # include <stdio.h> # include "exti.h" # include "timer.h" # include "rtc.h" # include "adc.h" # include "ds18b20.h" # include "ble.h" #include "esp8266.h" # include "wdg.h" # include "oled.h" # include "rfid_rc522.h" # include "infrared.h" # include "iic.h" # include "at24c08.h" u8 buff_tx[ 50 ]= "1234567890" ; u8 buff_rx[ 50 ]; u8 data = 88 ; u8 data2; int main () { u8 key; LED_Init (); KEY_Init (); BEEP_Init (); TIM1_Init ( 72 , 20000 ); //Auxiliary serial port 1 receiving, timeout time is 20ms USART_X_Init (USART1, 72 , 115200 ); IIC_Init (); //IIC bus initialization printf ( "usart1 ok\n" ); while ( 1 ) { key = KEY_Scanf (); if (key) { //AT24C08_WriteByte(100,50,buff_tx); //AT24C08_ReadByte(100,50,buff_rx); //printf("buff_rx=%s\n",buff_rx); //Test block 0 //data=AT24C08_ReadOneByte(0); //AT24C08_WriteOneByte(0,data+1); //printf("data=%d\n",data); //Test block 1 //data=AT24C08_ReadOneByte(300); //AT24C08_WriteOneByte(300,data+1); //printf("data=%d\n",data); //Test the second block //data=AT24C08_ReadOneByte(600); //AT24C08_WriteOneByte(600,data+1); //printf("data=%d\n",data); //Test the third block data = AT24C08_ReadOneByte ( 900 ); AT24C08_WriteOneByte ( 900 ,data+ 1 ); printf( "data=%d\n" ,data); } } } Copy code

Serial port debugging assistant source download address:  blog.csdn.net/xiaolong112...