最近学完C语言,在做手持风扇主板,我使用了一个数组和一个计数器读取预设好的档位值,然后赋值给CCAP寄存器,实现改变占空比。
const unsigned char ccapvalues[] = {0x38, 0x33, 0x2E, 0x25, 0x20, 0x16, 0x10, 0x00};
unsigned char ccapcounter;
我读手册时,看到一句话:时钟停振模式下,CPU 和全部的外设均停止工作,但 SRAM 和 XRAM 中的数据是一直维持不变的。
看到这句话之后,我想既然如此,那我这个计数器的值就不需要保存到eeprom了,毕竟我是软关机,单片机不会完全掉电。
然而当我写完代码之后,实际测试发现,CCAP计数器在从睡眠恢复之后,无论怎么设置都恢复到0。
即使是尝试将该UCHAR用idata和_at_命令固定在ram中的某个位置,它也会恢复到0。
这似乎不对?不是说进入掉电模式SRAM中的数据不会变吗?由于怎么改代码都得不到正确的结果,我索性就去尝试eeprom读写了
在看过手册之后,写了一段EEPROM的读写函数,我按照原来的思路,把eeprom读取函数放在了SLEEP函数中,唤醒后执行的地方。
void SLEEP(void){
//其他代码
EEPROM_WRITE(ccapcounter);//把计数器的值写入
PCON = 0X02;
/////////////////唤醒后从这里执行/////////////////
//其他代码
EEPROM_READ();//读取EEPROM,赋值给计数器
}
但是这么尝试之后,依然无法观察到从睡眠中唤醒计数器值不会被重置。
最后搞的我都开始怀疑我写的代码了,直接复制手册里的代码之后,发现还是不行,于是我就想着写一段用于验证eeprom读写功能的代码
http://www.stcaimcu.com/thread-18923-1-1.html
不负我所望,在这个代码中,成功验证了我写的EEPROM读写代码是完全正确的,既然可以正确读写,那又为什么计数器值还是被归零呢?我开始怀疑是不是代码其他部分把计数器值重置了。
检查之后也没有发现有哪里会把计数器给重置。
但是我看着睡眠函数里面的读取位置,我突然想到,我在主循环里再执行一遍读取行不行?说做就做,我用了一个用于初始化计数器值的bit量。
bit initccapcounter = 0;
void main(){
//其他代码
while(1){
if(!initccapcounter){
initccapcounter = 1;
EEPROM_READ();
}
结果还真实现了唤醒后计数器不归零的功能。
然后经过查证之后,发现是在执行完SLEEP函数之后,单片机会从复位向量地址重新执行程序,也就是变量可能在这里重新被初始化了!
也就是说,在我这个场景下,相当于是刚执行完EEPROM_READ,刚给计数器赋了值,然后你程序就把这个值清空了,所以才表现出了“没有读取成功的现象”!
但是我对这个问题也是一知半解,我不知道为什么我不不论是不给变量初值,还是用_at_把变量定位到IDATA,都没用,不过既然EEPROM已经成功了,我就不在乎这些试过的方案了。
到此为止,总算是解决了变量会被归零的问题。
|