找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 74|回復(fù): 5
打印 上一主題 下一主題
收起左側(cè)

SRAM中的變量,進(jìn)入掉電真的不變?

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:1155837 發(fā)表于 2025-7-4 21:17 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
最近學(xué)完C語言,在做手持風(fēng)扇主板,我使用了一個數(shù)組和一個計數(shù)器讀取預(yù)設(shè)好的檔位值,然后賦值給CCAP寄存器,實現(xiàn)改變占空比。
const unsigned char ccapvalues[] = {0x38, 0x33, 0x2E, 0x25, 0x20, 0x16, 0x10, 0x00};
unsigned char ccapcounter;

我讀手冊時,看到一句話:時鐘停振模式下,CPU 和全部的外設(shè)均停止工作,但 SRAM 和 XRAM 中的數(shù)據(jù)是一直維持不變的。
看到這句話之后,我想既然如此,那我這個計數(shù)器的值就不需要保存到eeprom了,畢竟我是軟關(guān)機(jī),單片機(jī)不會完全掉電。
然而當(dāng)我寫完代碼之后,實際測試發(fā)現(xiàn),CCAP計數(shù)器在從睡眠恢復(fù)之后,無論怎么設(shè)置都恢復(fù)到0。
即使是嘗試將該UCHAR用idata和_at_命令固定在ram中的某個位置,它也會恢復(fù)到0。
這似乎不對?不是說進(jìn)入掉電模式SRAM中的數(shù)據(jù)不會變嗎?由于怎么改代碼都得不到正確的結(jié)果,我索性就去嘗試eeprom讀寫了
在看過手冊之后,寫了一段EEPROM的讀寫函數(shù),我按照原來的思路,把eeprom讀取函數(shù)放在了SLEEP函數(shù)中,喚醒后執(zhí)行的地方。
void SLEEP(void){
//其他代碼
EEPROM_WRITE(ccapcounter);//把計數(shù)器的值寫入
PCON = 0X02;
/////////////////喚醒后從這里執(zhí)行/////////////////
//其他代碼
EEPROM_READ();//讀取EEPROM,賦值給計數(shù)器
}
但是這么嘗試之后,依然無法觀察到從睡眠中喚醒計數(shù)器值不會被重置。
最后搞的我都開始懷疑我寫的代碼了,直接復(fù)制手冊里的代碼之后,發(fā)現(xiàn)還是不行,于是我就想著寫一段用于驗證eeprom讀寫功能的代碼
http://www.stcaimcu.com/thread-18923-1-1.html
不負(fù)我所望,在這個代碼中,成功驗證了我寫的EEPROM讀寫代碼是完全正確的,既然可以正確讀寫,那又為什么計數(shù)器值還是被歸零呢?我開始懷疑是不是代碼其他部分把計數(shù)器值重置了。
檢查之后也沒有發(fā)現(xiàn)有哪里會把計數(shù)器給重置。
但是我看著睡眠函數(shù)里面的讀取位置,我突然想到,我在主循環(huán)里再執(zhí)行一遍讀取行不行?說做就做,我用了一個用于初始化計數(shù)器值的bit量。
bit initccapcounter = 0;
void main(){
//其他代碼
while(1){
        if(!initccapcounter){
        initccapcounter = 1;
        EEPROM_READ();

}
結(jié)果還真實現(xiàn)了喚醒后計數(shù)器不歸零的功能。
然后經(jīng)過查證之后,發(fā)現(xiàn)是在執(zhí)行完SLEEP函數(shù)之后,單片機(jī)會從復(fù)位向量地址重新執(zhí)行程序,也就是變量可能在這里重新被初始化了!
也就是說,在我這個場景下,相當(dāng)于是剛執(zhí)行完EEPROM_READ,剛給計數(shù)器賦了值,然后你程序就把這個值清空了,所以才表現(xiàn)出了“沒有讀取成功的現(xiàn)象”!
但是我對這個問題也是一知半解,我不知道為什么我不不論是不給變量初值,還是用_at_把變量定位到IDATA,都沒用,不過既然EEPROM已經(jīng)成功了,我就不在乎這些試過的方案了。
到此為止,總算是解決了變量會被歸零的問題。
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

沙發(fā)
ID:879809 發(fā)表于 2025-7-5 18:43 | 只看該作者
你需要修改startup.a51這個文件。
回復(fù)

使用道具 舉報

板凳
ID:1137639 發(fā)表于 2025-7-6 00:24 | 只看該作者
在手持風(fēng)扇主板開發(fā)中,你遇到的計數(shù)器在睡眠模式恢復(fù)后歸零的問題,本質(zhì)上是對單片機(jī)睡眠模式與程序執(zhí)行機(jī)制理解偏差導(dǎo)致的。盡管數(shù)據(jù)手冊表明SRAM在時鐘停振模式下能維持?jǐn)?shù)據(jù),但程序從睡眠喚醒后并非從斷點繼續(xù)執(zhí)行,而是會從復(fù)位向量地址重新啟動,這會導(dǎo)致全局變量和靜態(tài)變量按編譯設(shè)定的初始值重新初始化(如`ccapcounter`默認(rèn)歸零),即便用`_at_`命令定位到IDATA也無法改變這一初始化邏輯,因為變量初始化是程序啟動階段的固有流程。  你最初嘗試將EEPROM讀寫放在`SLEEP`函數(shù)中,誤以為喚醒后能直接沿用寫入的值,但實際程序重啟后會先執(zhí)行初始化代碼,此時EEPROM讀取的時機(jī)滯后于變量初始化,導(dǎo)致新值被初始值覆蓋。而將`EEPROM_READ()`放在主循環(huán)的條件判斷中(通過`initccapcounter`標(biāo)記避免重復(fù)讀取),確保了程序重啟后首次進(jìn)入主循環(huán)時立即用EEPROM數(shù)據(jù)覆蓋默認(rèn)初始化值,從而實現(xiàn)了計數(shù)器狀態(tài)的保持,這是利用程序執(zhí)行順序解決了初始化與數(shù)據(jù)恢復(fù)的時序沖突問題。  此案例揭示了單片機(jī)睡眠模式下的關(guān)鍵要點:睡眠喚醒本質(zhì)是一次程序重啟,變量會按編譯規(guī)則重新初始化,SRAM數(shù)據(jù)維持特性僅適用于未被程序主動修改的場景。因此,涉及狀態(tài)保持的應(yīng)用需在程序啟動流程中優(yōu)先完成非易失性數(shù)據(jù)(如EEPROM)的讀取,以覆蓋默認(rèn)初始化值,而非依賴SRAM的被動數(shù)據(jù)維持機(jī)制。這也驗證了嵌入式系統(tǒng)開發(fā)中“程序執(zhí)行流程控制”與“硬件特性利用”需協(xié)同設(shè)計的重要性。
回復(fù)

使用道具 舉報

地板
ID:384109 發(fā)表于 2025-7-6 10:22 | 只看該作者
你這是什么單片機(jī)啊,休眠喚醒跟復(fù)位操作一個效果,那還要休眠干什么,直接斷電不就好了
回復(fù)

使用道具 舉報

5#
ID:604453 發(fā)表于 2025-7-6 13:32 | 只看該作者
進(jìn)入休眠模式不變,掉電斷電會丟失的。
回復(fù)

使用道具 舉報

6#
ID:1133081 發(fā)表于 2025-7-6 14:55 | 只看該作者
樓主說的問題根本不存在,是樓主沒有設(shè)置好PCON寄存器。這是用STC8H3K48S2在官方例程基礎(chǔ)上改寫的測試程序,喚醒后的num值就是休眠前的值。
  1. #include <STC8H.H>
  2. #include "intrins.h"

  3. #define IDL             0x01                    //PCON.0
  4. #define PD              0x02                    //PCON.1
  5. #define uint unsigned int
  6. #define uchar unsigned char

  7. uchar code table[]={
  8.         0x3f,0x06,0x5b,0x4f,
  9.         0x66,0x6d,0x7d,0x07,
  10.         0x7f,0x6f,0x77,0x7c,
  11.         0x39,0x5e,0x79,0x71};
  12. uchar data dis_buf[8];

  13. uchar i;
  14. uint j;
  15. uint num=9990;
  16. void Delay1ms(void)        //@11.0592MHz
  17. {
  18.         unsigned char data i, j;

  19.         i = 15;
  20.         j = 90;
  21.         do
  22.         {
  23.                 while (--j);
  24.         } while (--i);
  25. }


  26. void main()
  27. {
  28.         P0M0 = 0x00;
  29.         P0M1 = 0x00;
  30.         P1M0 = 0x00;
  31.         P1M1 = 0x00;
  32.         P2M0 = 0x00;
  33.         P2M1 = 0x00;
  34.         P3M0 = 0x00;
  35.         P3M1 = 0x00;
  36.         P4M0 = 0x00;
  37.         P4M1 = 0x00;
  38.         P5M0 = 0x00;
  39.         P5M1 = 0x00;
  40.        
  41.         EX0 = 1;                                    //使能INT0中斷,用于喚醒MCU
  42.         EA = 1;

  43.         while (1)
  44.         {
  45.                 dis_buf[0]=table[num/1000%10];
  46.                 dis_buf[1]=table[num/100%10];
  47.                 dis_buf[2]=table[num/10%10];
  48.                 dis_buf[3]=table[num%10];
  49.                 P0=0x00;
  50.                 P2&=0xf0;
  51.                 P2|=~(0x01<<i);
  52.                 P0=dis_buf[i];
  53.                 i=++i%4;
  54.                 if(++j>=1000)
  55.                 {
  56.                         j=0;
  57.                         if(++num>9999)num=0;
  58.                 }
  59.                 if(!P33)//key
  60.                 {
  61.                         P0=0xff;
  62.                         P2=0xff;
  63.                         _nop_();
  64.                         _nop_();
  65.                         _nop_();
  66.                         _nop_();
  67. //                        PCON = IDL;                                 //MCU進(jìn)入IDLE模式
  68.                         PCON = PD;                                  //MCU進(jìn)入掉電模式
  69.                         _nop_();
  70.                         _nop_();
  71.                         _nop_();
  72.                         _nop_();
  73.                 }
  74.                 Delay1ms();
  75.         }
  76. }

  77. void INT0_Isr() interrupt 0//P3.2
  78. {
  79. //    外部中斷喚醒                                 //測試端口
  80. }
復(fù)制代碼
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表