前言
最近在写一个用到单片机掉电记忆的程序时,发现每一次记忆的都是0(一个固定的值),原因也找了好久,后来也成功找到了。
一、掉电记忆代码(不好的,有瑕疵的)
- 掉电初始化函数:
void LVD_Init()
{
PCON &= ~(0x20); //上电后需要清LVD中断标志位
ELVD = 1; //低压监测中断允许
PLVD = 1; //低压中断 优先级高
EA=1;
}
- 掉电中断服务函数:
void LVD_Routine(void) interrupt 6
{
uchar i;
// 断电要执行的操作//
IapEraseSector(0x0200);//擦除第二个扇区
if(LED1 == ON)
{
IapProgramByte(0x0200+1,ON);
}
else
{
IapProgramByte(0x0200+1,OFF);
}
while(PCON & (1<<5)) //检测是否仍然低电压
{
PCON = PCON & ~(1<<5); //低压检测标志清0
for(i=0; i<200; i++); //延时一下
}
}
二、问题分析:为什么存储的值是确定的(不是ON就是OFF)
- if(LED1 == ON):这一句的作用是判断LED1的状态,如果LED1熄灭就存储OFF,反之存储ON。但是很明显的错误就是断电后,LED1都是熄灭的状态,所以存储的值恒为OFF。
- IapEraseSector(0x0200);这一句也有很严重的问题,就是进行eeprom电擦除时是要电的,那么问题来了,单片机掉电后,哪里会有多余的电呢,很容易导致,还没擦除完毕,单片机就完全掉电了,后面的值就来不及存储。
三、问题解决:
- 可以用一个标志位跟随LED1,断电后存储这个标志位的值就可以了。
- 在单片机通电的时候进行eeprom的擦除。
- 加电容,掉电后有做足够的电执信完数据存储。
四、优化后的代码:
void LVD_Init()
{
PCON &= ~(0x20); //上电后需要清LVD中断标志位
ELVD = 1; //低压监测中断允许
PLVD = 1; //低压中断 优先级高
EA=1;
IapEraseSector(0x0200);//擦除第二个扇区
}
void LVD_Routine(void) interrupt 6
{
uchar i;
// 断电要执行的操作//
if(LED1_f == ON)
{
IapProgramByte(0x0200+1,ON);
}
else
{
IapProgramByte(0x0200+1,OFF);
}
while(PCON & (1<<5)) //检测是否仍然低电压
{
PCON = PCON & ~(1<<5); //低压检测标志清0
for(i=0; i<200; i++); //延时一下
}
}
总结
发现问题不重要,重要的是寻找解决问题的办法,不要害怕花时间,有一句话说的好:好事多磨。