51 microcontroller - simulates I2C bus communication with AT24C02

Table of contents

1. Write in front

2. Function description

3. Introduction to main modules

3.1 Introduction to I2C bus

3.2 I2C bus protocol

3.2.1 Data validity regulations

3.2.2 Start signal and stop signal 

3.2.3 Send response and receive response

3.2.4 The host sends a byte and receives a byte

3.3 Introduction to AT24C02

3.3 Byte writing and random reading

4. Test file test.c

5. Phenomenon description


1. Write in front

  • The AT24C02 chip has an I2C interface, but the 51 microcontroller does not have an I2C interface. A software program is used to simulate the I2C bus.
  • 51 microcontroller is the host machine, and AT24C02 is the slave machine. The most important thing in this experiment is to find out whether the master or the slave is sending or receiving data.
  • The default is for the host to control the SCL and SDA lines. If the slave wants to control the SDA line and sends data, the master must release the bus (SDA=1).

2. Function description

        Use the microcontroller to simulate I2C communication with AT24C02, write the data into AT24C02, and use the feature of AT24C02 to store data that will not be lost after power failure. After the microcontroller is restarted, the data at the corresponding address can be read out.

3. Introduction to main modules

3.1 Introduction to I2C bus

        The I2C bus (Inter IC Bus) has only two bidirectional signal lines. One is the data line SDA, and the other is the clock line SCL. There is a clock line and it is sent by the master and received by the slave, or sent by the slave and received by the master, so I2C is a synchronous, half-duplex communication method.

3.2 I2C bus protocol

3.2.1 Data validity regulations

        When the I2C bus transmits data, the data on the data line must remain stable during the period when the clock signal is high level. Only when the signal on the clock line is low level, the high level or low level state on the data line can Allow for changes.

3.2.2 Start signal and stop signal 

  • Start signal: When SCL is high level, SDA changes from high level to low level.
  • Stop signal: When SCL is high level, SDA changes from low level to high level.

        The start and stop signals are both sent by the host. After the start signal is generated, the bus is in an occupied state; after the stop signal is generated, the bus is in an idle state.

The start and stop signals are simulated by the program as follows:

/*
     *函数名:	I2C_star()
     *函数功能:I2C的起始信号
     *输入:	无
     *输出:	无
*/
void I2C_star()
{
	I2C_SDA=1;
	I2C_SCL=1;
	I2C_SDA=0;
	I2C_SCL=0;	
}
/*
     *函数名:	I2C_stop()
     *函数功能:I2C的停止信号
     *输入:	无
     *输出:	无
*/
void I2C_stop()
{
	 I2C_SDA=0;
	 I2C_SCL=1;
	 I2C_SDA=1;
}

3.2.3 Send response and receive response

        Send responses and receive responses are relative to the host. The response is a low-level pulse, and the non-response is a high-level pulse.

  • Send response: When the host receives a piece of data sent by the slave, the host sends a response signal to the slave, whether to continue sending data.
  • Receiving response: After the master sends a data to the slave, the slave sends a response signal by controlling SDA (the host wants to release the bus at this time ), and the host decides whether to send data based on the response signal.

 The program simulation is as follows:

/*
     *函数名:	 I2C_SendAck(bit ack)
     *函数功能:  主机发送应答
     *输入:	     ack:发送的一个应答
     *输出:	     无
*/
void I2C_SendAck(bit ack)//主机发送应答
{
	I2C_SDA=ack;
	I2C_SCL=1;
	I2C_SCL=0;
}
/*
     *函数名:	  I2C_ReadAck()
     *函数功能:   主机接收应答
     *输入:	      无
     *输出:	      ack:接收的应答
*/
bit I2C_ReadAck()//主机接收应答
{
	bit ack=0;
	I2C_SDA=1;//释放总线
	I2C_SCL=1;
	ack=I2C_SDA;
	I2C_SCL=0;
	return ack;
}

3.2.4 The host sends a byte and receives a byte

  1. The host sends a byte of data: when SCL is low, the host writes the data to the SDA line in sequence (high bit first), then pulls SCL high, and the slave will read the data bits while SCL is high, looping 8 times , you can send one byte of data.
  2. The host receives a byte of data: first the host releases the bus (SDA=1), when SCL is low, the slave writes the data to the SDA line in sequence (high bit first), and then pulls SCL high, the host will Read the data bits during normal times and cycle 8 times to receive one byte of data.

The procedure is as follows:

/*
     *函数名:	 I2C_Writebyte(unsigned char byte)
     *函数功能: I2C总线主机发送一个字节数据
     *输入:	 byte:要发送的字节数据
     *输出:	 无
*/
void I2C_Writebyte(unsigned char byte)//主机发送一个字节的数据
{
	unsigned char i=0;
	for(i=0;i<8;i++)
	{
		I2C_SDA=byte&(0x80>>i);
		I2C_SCL=1;
		I2C_SCL=0;
	}
}
/*
     *函数名:	 I2C_Readbyte()
     *函数功能: I2C总线主机接收一个字节数据
     *输入:	 无
     *输出:	 byte:读取的数据
*/
unsigned char I2C_Readbyte()//主机接收一个字节数据
{
	unsigned char i,byte=0;
	I2C_SDA=1;//释放总线
	for(i=0;i<8;i++)
	{
		I2C_SCL=1;
		if(I2C_SDA==1){byte|=(0x80>>i);}//I2C_SDA上的数据已经是从机发送的数据
		I2C_SCL=0;
	}
	return byte;
}

3.3 Introduction to AT24C02

        Our development board uses the AT24C02 (EEPROM) chip. This chip has an I2C communication interface. The data stored in the chip will not be lost even when the power is off, so it is usually used to store some more important data.

3.3 Byte writing and random reading

        I2C bus addressing can be divided into two types according to the number of slave address bits, one is 7 bits and the other is 10 bits. The bit definitions of the 7-bit addressing byte are as follows:

        Of the 7-bit addressing bits of a slave, 4 bits are fixed bits and 3 bits are programmable bits.

  •  The fixed value of AT24C02 is 1010, and the programmable bit value of this development board is 000. The slave address plus the read/write bit (0/1) is the first byte after the start signal.
  1.  The order of byte writing: start signal + slave address with read/write bit (0/1) + receiving response + address specifying the write data + receiving response + written data + receiving response + stop signal.
  2.  The sequence of random reading: start signal + slave address with read/write bit (0/1) + receive response + address specifying the read data + receive response + start signal + slave address with read/write bit (0 /1) + receive response + host receives data + send response + stop signal.

 The procedure is as follows:

#define AT24C02_address 0xA0  //AT24C02的地址
/*
     *函数名:	AT24C02_Writebyte(unsigned char word_address,byte)
     *函数功能:向AT24C02中的某个地址写入一个字节数据
     *输入:	word_address:字节地址	 byte:写入的字节数据
     *输出:	无
*/
void AT24C02_Writebyte(unsigned char word_address,byte)
{
	bit ack=0;
	I2C_star();
	I2C_Writebyte(AT24C02_address);
	ack=I2C_ReadAck();
	I2C_Writebyte(word_address);
	ack=I2C_ReadAck();
	I2C_Writebyte(byte);
	ack=I2C_ReadAck();
	I2C_stop();
}
/*
     *函数名:	  AT24C02_Readbyte(unsigned char word_address)
     *函数功能:  主机读取AT24C02的指定地址的数据
     *输入:	  word_address:数据的地址
     *输出:	  byte:被读取的字节数据
*/
unsigned char AT24C02_Readbyte(unsigned char word_address)
{
	unsigned char byte=0;
	bit ack=0;
	I2C_star();
	I2C_Writebyte(AT24C02_address);
	ack=I2C_ReadAck();
	I2C_Writebyte(word_address);
	ack=I2C_ReadAck();
	I2C_star();
	I2C_Writebyte(AT24C02_address|0x01);
	ack=I2C_ReadAck();
	byte=I2C_Readbyte();
	I2C_SendAck(1);
	I2C_stop();
	return byte;
}

4. Test file test.c

#include <REGX52.H>
#include"I2C.h"
#include"LCD1602.h"
#include"AT24C02.h"
#include"Independentkey.h"
#include"Delay.h"
int main()
{
	unsigned char keynum,num=0;
	LCD_Init();
	LCD_ShowNum(1,1,0,3);
	AT24C02_Writebyte(0x01,1);
	Delay(5);
	AT24C02_Writebyte(0x02,2);
	Delay(5);
	AT24C02_Writebyte(0x03,3);
	Delay(5);
	AT24C02_Writebyte(0x04,4);
	Delay(5);
	while(1)
	{
		keynum=Independentkey();
		if(keynum!=0)
		{
			 if(keynum==1)
			 {
			 	num=AT24C02_Readbyte(0x01);
				LCD_ShowNum(1,1,num,3);
			 }
			 if(keynum==2)
			 {
			 	num=AT24C02_Readbyte(0x02);
				LCD_ShowNum(1,1,num,3);
			 }
			 if(keynum==3)
			 {
			 	num=AT24C02_Readbyte(0x03);
				LCD_ShowNum(1,1,num,3);
			 }
			 if(keynum==4)
			 {
			 	num=AT24C02_Readbyte(0x04);
				LCD_ShowNum(1,1,num,3);
			 }
		}
	}
}

5. Phenomenon description

        Write 1, 2, 3, and 4 at addresses 0x01, 0x02, 0x03, and 0x04 of AT24C02, then press the independent buttons to read them out respectively (can be powered off without losing data), and displayed on LCD1602.

  • Written at the back: When you encounter something you don’t understand or something goes wrong with the program, first of all you shouldn’t complain about why it’s so difficult. First, calm down. If you don’t understand something once, I’ll listen to it twice. If you don’t understand both sides, I’ll listen to it three times. Until you understand. You can also go out for a walk, clarify your thoughts, and then go back and watch the video. There are some things that others think you know but don’t say, but in fact you don’t know. This leads to confusion in your thinking and you wonder why it is like this. Stuck there for a long time. The content written above is the points I didn’t know and the points worth noting while watching the video. If the program cannot run, carefully look for the cause of the problem. I used to think that Warning is of no use. It just reports a warning, but the program can still run. This time I spent a long time looking for the problem. It turns out that there is an if () statement that only checks for equality. There was a "=" sign, and the compiler reported a warning but no error. I thought it was somewhere in my program that was written incorrectly, and I changed it again, which wasted a lot of time. Finally, the most important thing when encountering a problem is to calm down, carefully find the cause of the problem, and then solve the problem.

Guess you like

Origin blog.csdn.net/ssssshhbh/article/details/129220526