找回密码
 立即注册
查看: 25|回复: 4

SRAM中保存的变量,进入睡眠后真的不变?

[复制链接]
  • 打卡等级:偶尔看看I
  • 打卡总天数:10
  • 最近打卡:2025-07-05 10:36:05
已绑定手机

7

主题

11

回帖

99

积分

注册会员

积分
99
发表于 昨天 21:15 | 显示全部楼层 |阅读模式
最近学完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已经成功了,我就不在乎这些试过的方案了。
到此为止,总算是解决了变量会被归零的问题。
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:227
  • 最近打卡:2025-07-05 09:24:45
已绑定手机

74

主题

2074

回帖

4620

积分

荣誉版主

无情的代码机器

积分
4620
发表于 昨天 23:18 | 显示全部楼层
"然后经过查证之后,发现是在执行完SLEEP函数之后,单片机会从复位向量地址重新执行程序,也就是变量可能在这里重新被初始化了!"


休眠是休眠,复位是复位。没看到在哪执行的SLEEP,上传完整代码看看。
SLEEP写入前也没见擦除函数。

之前做的低功耗测试,通过P2 = 0x0F;可以观察反复唤醒是继续执行,不是重新复位的:
https://www.stcaimcu.com/forum.p ... 8635&pid=172110
三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:487
  • 最近打卡:2025-07-05 00:21:01
已绑定手机

81

主题

5284

回帖

9477

积分

超级版主

DebugLab

积分
9477
发表于 13 小时前 | 显示全部楼层
初始化要正确设置IAP_TPS
CPU时钟频率接近极限频率时还要设置IRCDB=16
建议省电模式之前,时钟设置为较低频率(如12M)并延时等待时钟稳定,再进入省电模式,唤醒后再恢复原来的时钟频率
DebugLab
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:10
  • 最近打卡:2025-07-05 10:36:05
已绑定手机

7

主题

11

回帖

99

积分

注册会员

积分
99
发表于 2 小时前 | 显示全部楼层
erci*** 发表于 2025-7-4 23:18
"然后经过查证之后,发现是在执行完SLEEP函数之后,单片机会从复位向量地址重新执行程序,也就是变量可能在 ...

擦除了,在我提供的那个链接里面就是我用的eeprom读写代码,会在写入前擦除一遍。我这里只是简单写的想表示执行过程的,EEPROM是可以正常读写的。至于你提到唤醒问题,我这里是变量被清零了,不是IO状态的寄存器,我做出执行完SLEEP函数之后变量会被清零的判断是因为,我把EEPROM读函数从SLEEP函数的末尾移出之后,立刻就可以正常恢复到睡眠前的变量值了,这只能证明在从进入掉电模式的函数退出之后,他确实经历过一次变量清零。我再试试在变量声明时不规定初值

点评

看下这个帖子,唤醒后将休眠前收到的数据发出: 新手请教大佬AI8G1K08的程序问题 - 综合讨论 国芯技术交流网站 - AI32位8051交流社区  详情 回复 发表于 2 小时前
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:227
  • 最近打卡:2025-07-05 09:24:45
已绑定手机

74

主题

2074

回帖

4620

积分

荣誉版主

无情的代码机器

积分
4620
发表于 2 小时前 | 显示全部楼层
李*** 发表于 2025-7-5 10:36
擦除了,在我提供的那个链接里面就是我用的eeprom读写代码,会在写入前擦除一遍。我这里只是简单写的想表 ...


看下这个帖子,唤醒后将休眠前收到的数据发出:

新手请教大佬AI8G1K08的程序问题 - 综合讨论 国芯技术交流网站 - AI32位8051交流社区
三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-7-5 13:32 , Processed in 0.115758 second(s), 76 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表