有关AT24C02/04/08的区别:02有2k的空间,04有4k,08有8k,每2k作为一个page;
器件地址的区别:
根据芯片手册:
可以看到:对于2k的器件,A2,A1,A0均作为地址位;对于4k的器件,A2和A1作为地址位,而A0位则作为寻页位,也就是A0为0时,选定第一页,A0为1时,选定第二页;而对于8k的器件,仅有A2位作为地址位,而A1和A0均作为寻页位,当A1A0为:00,01,10,11时,依次对应第1,2,3,4页。
而最低位为确定读还是写操作,为0时表示写操作,1表示读操作。
所以对于本次使用的AT24C08,进行写操作时,其器件地址可以为 0xA0 | XX(XX为00,01,10,11);进行读操作时,其器件地址可以为 0xA1 | XX(XX为00,01,10,11).
对应写操作的时序图:
/*
*@breif 指定地址写入一个字节
*@param 器件地址(写):0xA0|XX,XX可以为00,01,10,11,表示不同页(总共1024k)
数据所在地址:0x00~0xFF
要写入的一个字节:Data
*@retval 无
*/
void AT24C08_WriteByte(uint8_t DeviceAdd_W,uint8_t DataAdd,uint8_t Data)
{
IIC_Start();
IIC_Send_Byte(DeviceAdd_W);
IIC_Wait_Ack();
IIC_Send_Byte(DataAdd);
IIC_Wait_Ack();
IIC_Send_Byte(Data);
IIC_Wait_Ack();
IIC_Stop();
Delay_ms(2);
}
值得注意的是:进行EEPROM写操作是需要一定的写入时间,否则数据会产生混乱。
对应读操作的时序图:
/*
*@breif 指定地址读取一个字节
*@param 器件地址(写和读):0xA0|XX,XX可以为00,01,10,11,表示不同页(总共1024k)
数据所在地址:0x00~0xFF
*@retval 读取到的数据:Data
*/
uint8_t AT24C08_ReadByte(uint8_t DeviceAdd_W,uint8_t DeviceAdd_R,uint8_t DataAdd)
{
uint8_t Data;
IIC_Start();
IIC_Send_Byte(DeviceAdd_W);
IIC_Wait_Ack();
IIC_Send_Byte(DataAdd);
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(DeviceAdd_R);
IIC_Wait_Ack();
Data = IIC_Read_Byte(0);//No Ack
IIC_Stop();
return Data;
}
而进行EEPROM读操作连续读是没有问题的。
主函数进行验证:
#include "stm32f10x.h" // Device header
#include "I2C.h"
#include "AT24C08.h"
#include "OLED.h"
#include "Delay.h"
int main(void)
{
uint8_t Num1 = 0,Num2 = 0,Num3 = 0,Num4 = 0;
OLED_Init();
IIC_Init();
AT24C08_WriteByte(0xA0,0x00,11);//在第1页的0x00写11
AT24C08_WriteByte(0xA2,0x00,22);//在第2页的0x00写22
AT24C08_WriteByte(0xA4,0x00,33);//在第3页的0x00写33
AT24C08_WriteByte(0xA6,0x00,44);//在第4页的0x00写44
Num1 = AT24C08_ReadByte(0xA0,0xA1,0x00);
Num2 = AT24C08_ReadByte(0xA2,0xA3,0x00);
Num3 = AT24C08_ReadByte(0xA4,0xA5,0x00);
Num4 = AT24C08_ReadByte(0xA6,0xA7,0x00);//逐个读取
OLED_ShowString(2,1,"Read Num:");
while(1)
{
OLED_ShowNum(2,10,Num1,3);
Delay_s(1);
OLED_ShowNum(2,10,Num2,3);
Delay_s(1);
OLED_ShowNum(2,10,Num3,3);
Delay_s(1);
OLED_ShowNum(2,10,Num4,3);
Delay_s(1);
}
}
最终结果: