【嵌入式硬件芯片开发笔记】EEPROM芯片M24C32配置流程
32-Kbit serial I²C bus EEPROM - 105°C operation
适用于M24C32/M24C32-DRE
读取存储的从机地址为:0x50
读取标识页面的从机地址为:0x58
WC引脚接地,存储可以进行写操作
地址长度为16位
存储地址:0x0000-0x0FFF,即4096个Bytes,32K-Bits
标识页面地址:0x0000-0x001F,即32个Bytes
标识页面在进行写操作时,b10为0,即add &= ~(1<<10)
开始运行
- 检查从机设备是否回应
- 读取制造商代码,并对比是否为0x20、0xE0、0x0C
初始化
按要求进行读写操作
- 在Mem地址0x0000-0x0007范围内进行读写测试:清空该区域(写入0x00);依次写入8、9、A、B、C、D、F
- 编译时间操作:
共分3块区域,用于存储当前编译时间、中间编译时间、上次编译时间,分别为0x0008-0x000E,0x0010-0x0006,0x0018-0x001E;且正常写入一次后,0x000F、0x0017、0x001F都为1。
时间存储格式为:yy yy mm dd hh mm ss 1
以十进制的方式,由低到高存储到每个寄存器中,比如2022/11/29 16:45:30,存储后为:
20d 22d 11d 29d 16d 45d 30d 1d,共8个地址存储64位数据
当前编译时间每一次运行都会被写入到0x0008-0x000E中。
当前时间与中间时间相同时,输出“上次运行后未重新编译”;当前时间与中间时间不同时,将中间时间写入到上次时间中,再将当前时间写入到中间时间中;上次时间标志0x001F的值不为1时,将当前时间写入到上次时间中,否则读取上次时间。
以下表格为三种时间地址范围在不同运行状态下的结果:(数字越大表示时间越靠后,为0表示首次运行)
代码例程
static char now_date[16] = __DATE__;
static char now_time[16] = __TIME__;
static char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
/*!
* @brief 初始化M24C32
*
* @param None
*
* @return 0/1: 错误/正确标志
*/
uint8_t Init_M24C32(void)
{
uint8_t dat=0;
uint32_t dat_32=0;
uint8_t i=0;
char strings[]="";
int int_data[3]={0,0,0};
uint8_t now_time_buf[8];
uint8_t last_time_buf[8];
uint8_t mid_time_buf[8];
if(I2C_Judge(&hi2c2,M24C32_Mem_Slave_Add)!=true || I2C_Judge(&hi2c2,M24C32_Id_Slave_Add)!=true)
{
return 0;
}
dat_32=I2C_Read_y(&hi2c1,M24C32_Id_Slave_Add,0x0000,2,3,true);
if(dat_32!=0x0020E00C)
{
return 0;
}
printf("[INFO] 开始Mem写入测试\n");
dat=0;
for(i=0;i<8;i++)
{
dat=0;
I2C_Write_x(&hi2c1,M24C32_Mem_Slave_Add,0x0000+i,2,&dat,1,true);
if(I2C_Read_y(&hi2c1,M24C32_Mem_Slave_Add,0x0000+i,2,1,true)==0)
{
printf("[INFO] Mem 0x000%d 清空正确: %02X\n",i,dat);
}
else
{
printf("[INFO] Mem 0x000%d 清空错误: %02X\n",i,dat);
printf("[INFO] Mem 清空中断\n");
return 0;
}
dat=i+8;
I2C_Write_x(&hi2c1,M24C32_Mem_Slave_Add,0x0000+i,2,&dat,1,true);
if(I2C_Read_y(&hi2c1,M24C32_Mem_Slave_Add,0x0000+i,2,1,true)==i+8)
{
printf("[INFO] Mem 0x000%d 写入正确: %02X\n",i,dat);
}
else
{
printf("[INFO] Mem 0x000%d 写入错误: %02X\n",i,dat);
printf("[INFO] Mem 写入中断\n");
return 0;
}
}
sscanf(now_date, "%s %d %d", strings, &int_data[0], &int_data[1]);
int_data[2]=(strstr(month_names, strings)-month_names)/3+1;
dat=(uint8_t)(int_data[1]/100);
I2C_Write_x(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x08,2,&dat,1,true);
dat=(uint8_t)(int_data[1]%100);
I2C_Write_x(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x09,2,&dat,1,true);
dat=(uint8_t)int_data[2];
I2C_Write_x(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x0A,2,&dat,1,true);
dat=(uint8_t)int_data[0];
I2C_Write_x(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x0B,2,&dat,1,true);
sscanf(now_time, "%d:%d:%d",&int_data[0], &int_data[1],&int_data[2]);
dat=(uint8_t)int_data[0];
I2C_Write_x(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x0C,2,&dat,1,true);
dat=(uint8_t)int_data[1];
I2C_Write_x(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x0D,2,&dat,1,true);
dat=(uint8_t)int_data[2];
I2C_Write_x(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x0E,2,&dat,1,true);
dat=1;
I2C_Write_x(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x0F,2,&dat,1,true);
for(i=0;i<8;i++)
{
now_time_buf[i]=I2C_Read_y(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x08+i,2,1,true);
mid_time_buf[i]=I2C_Read_y(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x10+i,2,1,true);
}
printf("[INFO] 写入当前编译时间:%02d%02d/%02d/%02d %02d:%02d:%02d\n",
now_time_buf[0],
now_time_buf[1],
now_time_buf[2],
now_time_buf[3],
now_time_buf[4],
now_time_buf[5],
now_time_buf[6]);
if( now_time_buf[0]!=mid_time_buf[0] ||
now_time_buf[1]!=mid_time_buf[1] ||
now_time_buf[2]!=mid_time_buf[2] ||
now_time_buf[3]!=mid_time_buf[3] ||
now_time_buf[4]!=mid_time_buf[4] ||
now_time_buf[5]!=mid_time_buf[5] ||
now_time_buf[6]!=mid_time_buf[6] )
{
for(i=0;i<8;i++)
{
dat=mid_time_buf[i];
I2C_Write_x(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x18+i,2,&dat,1,true);
dat=now_time_buf[i];
I2C_Write_x(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x10+i,2,&dat,1,true);
}
}
else
{
printf("[INFO] 上次运行后未重新编译\n");
}
if(I2C_Read_y(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x1F,2,1,true)==1)
{
for(i=0;i<8;i++)
{
last_time_buf[i]=I2C_Read_y(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x18+i,2,1,true);
}
printf("[INFO] 上次编译时间:%02d%02d/%02d/%02d %02d:%02d:%02d\n",
last_time_buf[0],
last_time_buf[1],
last_time_buf[2],
last_time_buf[3],
last_time_buf[4],
last_time_buf[5],
last_time_buf[6]);
}
else
{
printf("[INFO] 当前编译时间:%s %s\n",now_date,now_time);
sscanf(now_date, "%s %d %d", strings, &int_data[0], &int_data[1]);
int_data[2]=(strstr(month_names, strings)-month_names)/3+1;
dat=(uint8_t)(int_data[1]/100);
I2C_Write_x(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x18,2,&dat,1,true);
dat=(uint8_t)(int_data[1]%100);
I2C_Write_x(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x19,2,&dat,1,true);
dat=(uint8_t)int_data[2];
I2C_Write_x(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x1A,2,&dat,1,true);
dat=(uint8_t)int_data[0];
I2C_Write_x(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x1B,2,&dat,1,true);
sscanf(now_time, "%d:%d:%d",&int_data[0], &int_data[1],&int_data[2]);
dat=(uint8_t)int_data[0];
I2C_Write_x(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x1C,2,&dat,1,true);
dat=(uint8_t)int_data[1];
I2C_Write_x(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x1D,2,&dat,1,true);
dat=(uint8_t)int_data[2];
I2C_Write_x(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x1E,2,&dat,1,true);
dat=1;
I2C_Write_x(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x1F,2,&dat,1,true);
printf("[INFO] 写入当前编译时间至上次编译时间:%02d%02d/%02d/%02d %02d:%02d:%02d\n",
I2C_Read_y(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x18,2,1,true),
I2C_Read_y(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x19,2,1,true),
I2C_Read_y(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x1A,2,1,true),
I2C_Read_y(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x1B,2,1,true),
I2C_Read_y(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x1C,2,1,true),
I2C_Read_y(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x1D,2,1,true),
I2C_Read_y(&hi2c1,M24C32_Mem_Slave_Add,0x0000+0x1E,2,1,true));
}
return 1;
}