EEPROM知识点总结
- 要点1—驱动代码编写
- 要点2:
-
- (1)有符号6位数的存取
- (2)16位有符号数的存储
- 要点3——必须加延时
- 要点4——几乎每届省赛都会遇到的问题(重要)
要点1—驱动代码编写
蓝桥杯比赛时会给模拟的iic驱动代码,也就是下面这两个.c和.h文件。我们需要做的是,根据它提供的AT24C02数据手册中的时序图编写两个函数来实现对EEPROM的读写操作。
我建议大家能够理解这两个时序图,看着时序图来编写读写函数,轻松的多,完全不需要背过下面这两个函数。(时序图就在数据手册中)
在数据手册中找到这两个时序图。
要点2:
(1)有符号6位数的存取
上面那两个读写函数是对 unsigned char 类型数据,也就是8位无符号数操作的。有时候我们需要存储16位无符号数的时候,可以采取这样的方法:
void write_16(unsigned char add,u16 data)
{
unsigned char a,b;
a=data/256;
b=data%256;
i2c_write(add,b);Delay_Ms(5);
i2c_write(add+1,a);
}
u16 read_16(unsigned char add)
{
u16 a;
unsigned char c,b;
c=i2c_read(add);Delay_Ms(5);
b=i2c_read(add+1);
a=c+b*256;
return a;
}
(2)16位有符号数的存储
需要先明白一点,有符号数和无符号数在存储器里面都是由0和1组成的,有符号数只不过是把最高位用做符号位(1代表复数,0代表正数)。所以,我想说的是,存储16位有符号数时也可以用16位无符号数的存储方法。只需要在读取时加一个强制转换即可。
short tem_up; //定义一个16位有符号数
......//没有必要展示的代码就略过了
......
......
tem_up=(short)read_16(0x03);//加个强制转换 ,妥妥的
要点3——必须加延时
每两个读取或者写入函数之间必须加5毫秒延时,是必须加。如果不加的话,数据非常容易乱(亲身体验)。
原因是,EEPROM外设的读取速度是跟不上MCU的运行速度的,需要让MCU停下来等待一会儿。5ms咱们看着不起眼,对于CPU来说,已经是很长一段时间了。
要点4——几乎每届省赛都会遇到的问题(重要)
以第七届省赛做一个分析(只关注EEPROM部分):
可以看到,题目要求,设备第一次上电,从EEPROM中读取到的初始值为30、50、70,之后每次修改这三个数值,都将具体值存入EEPROM,设备再次上电,就可以从EEPROM中读取具体值。
后半句话是没问题的,可以通过程序来实现,只要在程序的最前面加一个读取EEPROM的函数就好了。
问题在前面,题目规定了读取的初值,可是,怎么才能够保证你读取到的数值是“30、50、70”呢?要知道,把程序下载到一块新板子上,EEPROM中存储的数值是不确定的。
有小伙伴可能会想,这还不简单,在程序最前面加一个写入函数不就好了,把“30、50、70”给提前写到新板子上,先写好,再读取。可是这就会导致,之后每次上电复位,读取到的都是“30、50、70”。这就与题目要求的“再次上电,读取到修改值”不符了。
针对这个问题,这里我提供一个程序上的解决方案:
- 代码的具体思路
要想实现,第一次读取到的是自己设定的初值,之后读取到的是修改值。那就需要加一个判断语句,如果判断为真,就将初始值“30、50、70”写入到板子上,判断为假,就不写入初始值。而且,这个判断语句只需要执行一次。 - 具体代码:
int main()
{
char string[20];
ADC_init();
LED_Init();
SysTickInit();
Buzzer_Init();
i2c_init();
Usart2_init();
key_init();
STM3210B_LCD_Init();
LCD_Clear(Blue);
LCD_SetBackColor(Blue);
LCD_SetTextColor(White);
if(Read_AT24c02(0x06)!=2) //判断
{
Write_AT24c02(0x01,30); DelayMS(5);
Write_AT24c02(0x02,50); DelayMS(5);
Write_AT24c02(0x03,70); DelayMS(5);
Write_AT24c02(0x06,2); //加了这个语句之后,就可以让这个判断只执行一次
DelayMS(5);
}
Level[0]=Read_AT24c02(0x01);DelayMS(5);
Level[1]=Read_AT24c02(0x02);DelayMS(5);
Level[2]=Read_AT24c02(0x03);DelayMS(5);
关键是判断条件的确定,我采取的是随遍读取一个EEPROM的地址,他只有256分之一的概率等于2,就意味着这段代码,可以成功的概率是256分之255。当然,如果觉得256分之一还是太大的话,可以这样写:
if(Read_AT24c02(0x06)!=2&&Read_AT24c02(0xaa)!=15) //地址和数值都是瞎写的
{
Write_AT24c02(0x01,30); DelayMS(5);
Write_AT24c02(0x02,50); DelayMS(5);
Write_AT24c02(0x03,70); DelayMS(5);
Write_AT24c02(0x06,2); //加了这个语句之后,就可以让这个判断只执行一次
DelayMS(5);
Write_AT24c02(0xaa,15);
DelayMS(5);
}
这样,概率就变成了256的平方分之一。(意义不大,抖个机灵而已)
这些都是我一点点总结的知识点,要是有对您有帮助的话,就给点个赞吧,球球了!