一、先用抽象法说明原理,让原理变得简单易懂:
1、向AT24C02写入数据:
有个关系户,他想安排自己的儿子进某个大厦里某个楼层的公司,那么他就要先找到这个公司的地址,然后再找到该公司是第几楼,最后把自己儿子安排进这个楼所在的公司。
说明:
(1)找到公司所在大厦:写入设备地址
(3)找到公司楼层:要写入数据的地址,也就是你想把数据存哪个数据存储单元
(4)儿子:你要写入的数据
2、向AT24C02读取数据:
儿子下班了,要老爸接他下班,但是老爸没空,打电话给司机,告诉司机公司所在的大厦地址,公司楼层,然后司机到了这个地址,问HR小姐姐找要找的人,司机准备接待,最后HR带人来了。
说明:
(1)司机需要先找到正确的大厦(写入设备地址0xA0)
(2)然后精确到具体楼层(写入存储地址Address)
(3)司机开始准备接待(写入0xA1)
(4)HR小姐姐找到了指定的人,并带来司机面前(读取数据Temp)
(5)接到后立刻离开(NACK+Stop)
二、原理图
1、设备地址:其中A2、A1、A0都是0,所以唯一要改的就是R/W
2、写入流程图:
3、读取流程图:
三、代码:
1、重点代码:(注:能看懂这里就可以了)
/* 参数:Address:范围是0x00 到 0xFF, Data:范围是0x00到0xff(0 - 255) 功能:向某个数据存储地址Address写入数据Data 返回值:无 */ void AT24C02_Write(unsigned char Address,unsigned char Data) { I2CStart(); I2CSendByte(0xA0); I2CWaitAck(); I2CSendByte(Address); I2CWaitAck(); I2CSendByte(Data); I2CWaitAck(); I2CStop(); } /* 参数:Address:范围是0x00 到 0xFF 功能:向某个数据存储地址Address读取数据 返回值:Temp */ unsigned char AT24C02_Read(unsigned char Address) { unsigned char Temp; I2CStart(); I2CSendByte(0xA0); I2CWaitAck(); I2CSendByte(Address); I2CWaitAck(); I2CStart(); I2CSendByte(0xA1); I2CWaitAck(); Temp = I2CReceiveByte(); I2CSendAck(1); I2CStop(); return Temp; }
2、主要代码:(注:并非所有代码,直接复制运行必错)
/* # I2C代码片段说明 1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。 2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题 中对单片机时钟频率的要求,进行代码调试和修改。 */ #include "sys.h" #define DELAY_TIME 10 // static void I2C_Delay(unsigned char n) { do { _nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_(); } while(n--); } // void I2CStart(void) { sda = 1; scl = 1; I2C_Delay(DELAY_TIME); sda = 0; I2C_Delay(DELAY_TIME); scl = 0; } // void I2CStop(void) { sda = 0; scl = 1; I2C_Delay(DELAY_TIME); sda = 1; I2C_Delay(DELAY_TIME); } // void I2CSendByte(unsigned char byt) { unsigned char i; for(i=0; i<8; i++){ scl = 0; I2C_Delay(DELAY_TIME); if(byt & 0x80){ sda = 1; } else{ sda = 0; } I2C_Delay(DELAY_TIME); scl = 1; byt <<= 1; I2C_Delay(DELAY_TIME); } scl = 0; } // unsigned char I2CReceiveByte(void) { unsigned char da; unsigned char i; for(i=0;i<8;i++){ scl = 1; I2C_Delay(DELAY_TIME); da <<= 1; if(sda) da |= 0x01; scl = 0; I2C_Delay(DELAY_TIME); } return da; } // unsigned char I2CWaitAck(void) { unsigned char ackbit; scl = 1; I2C_Delay(DELAY_TIME); ackbit = sda; scl = 0; I2C_Delay(DELAY_TIME); return ackbit; } // void I2CSendAck(unsigned char ackbit) { scl = 0; sda = ackbit; I2C_Delay(DELAY_TIME); scl = 1; I2C_Delay(DELAY_TIME); scl = 0; sda = 1; I2C_Delay(DELAY_TIME); } /* 参数:Address:范围是0x00 到 0xFF, Data:范围是0x00到0xff(0 - 255) 功能:向某个数据存储地址Address写入数据Data 返回值:无 */ void AT24C02_Write(unsigned char Address,unsigned char Data) { I2CStart(); I2CSendByte(0xA0); I2CWaitAck(); I2CSendByte(Address); I2CWaitAck(); I2CSendByte(Data); I2CWaitAck(); I2CStop(); } /* 参数:Address:范围是0x00 到 0xFF 功能:向某个数据存储地址Address读取数据 返回值:Temp */ unsigned char AT24C02_Read(unsigned char Address) { unsigned char Temp; I2CStart(); I2CSendByte(0xA0); I2CWaitAck(); I2CSendByte(Address); I2CWaitAck(); I2CStart(); I2CSendByte(0xA1); I2CWaitAck(); Temp = I2CReceiveByte(); I2CSendAck(1); I2CStop(); return Temp; }
unsigned char temp; void main() { AT24C02_Write(0x01,122); // 向0x01数据存储地址写入122 while(1) { temp = AT24C02_Read(0x01); // 从0x01数据存储地址读取数据,理论上应该是122 SMG(1,temp / 100); // 显示百位 SMG(2,temp % 100 / 10); // 显示十位 SMG(3,temp % 10); // 显示个位 } }