久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

標題: SRAM中的變量,進入掉電真的不變? [打印本頁]

作者: 千早愛音愛玩51    時間: 2025-7-4 21:17
標題: SRAM中的變量,進入掉電真的不變?
最近學完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已經成功了,我就不在乎這些試過的方案了。
到此為止,總算是解決了變量會被歸零的問題。

作者: rundstedt    時間: 2025-7-5 18:43
你需要修改startup.a51這個文件。
作者: 622323wjl    時間: 2025-7-6 00:24
在手持風扇主板開發中,你遇到的計數器在睡眠模式恢復后歸零的問題,本質上是對單片機睡眠模式與程序執行機制理解偏差導致的。盡管數據手冊表明SRAM在時鐘停振模式下能維持數據,但程序從睡眠喚醒后并非從斷點繼續執行,而是會從復位向量地址重新啟動,這會導致全局變量和靜態變量按編譯設定的初始值重新初始化(如`ccapcounter`默認歸零),即便用`_at_`命令定位到IDATA也無法改變這一初始化邏輯,因為變量初始化是程序啟動階段的固有流程。  你最初嘗試將EEPROM讀寫放在`SLEEP`函數中,誤以為喚醒后能直接沿用寫入的值,但實際程序重啟后會先執行初始化代碼,此時EEPROM讀取的時機滯后于變量初始化,導致新值被初始值覆蓋。而將`EEPROM_READ()`放在主循環的條件判斷中(通過`initccapcounter`標記避免重復讀。,確保了程序重啟后首次進入主循環時立即用EEPROM數據覆蓋默認初始化值,從而實現了計數器狀態的保持,這是利用程序執行順序解決了初始化與數據恢復的時序沖突問題。  此案例揭示了單片機睡眠模式下的關鍵要點:睡眠喚醒本質是一次程序重啟,變量會按編譯規則重新初始化,SRAM數據維持特性僅適用于未被程序主動修改的場景。因此,涉及狀態保持的應用需在程序啟動流程中優先完成非易失性數據(如EEPROM)的讀取,以覆蓋默認初始化值,而非依賴SRAM的被動數據維持機制。這也驗證了嵌入式系統開發中“程序執行流程控制”與“硬件特性利用”需協同設計的重要性。
作者: 人中狼    時間: 2025-7-6 10:22
你這是什么單片機啊,休眠喚醒跟復位操作一個效果,那還要休眠干什么,直接斷電不就好了
作者: lzuoxin    時間: 2025-7-6 13:32
進入休眠模式不變,掉電斷電會丟失的。
作者: WL0123    時間: 2025-7-6 14:55
樓主說的問題根本不存在,是樓主沒有設置好PCON寄存器。這是用STC8H3K48S2在官方例程基礎上改寫的測試程序,喚醒后的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進入IDLE模式
  68.                         PCON = PD;                                  //MCU進入掉電模式
  69.                         _nop_();
  70.                         _nop_();
  71.                         _nop_();
  72.                         _nop_();
  73.                 }
  74.                 Delay1ms();
  75.         }
  76. }

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

作者: 千早愛音愛玩51    時間: 2025-7-8 23:57
rundstedt 發表于 2025-7-5 18:43
你需要修改startup.a51這個文件。

改了,添加了一個清空ram區域的跳過程序,比如初始化到0x30就跳過到0x31繼續,把這個char值用_at_定在0x30,但沒成功
作者: 千早愛音愛玩51    時間: 2025-7-9 00:14
WL0123 發表于 2025-7-6 14:55
樓主說的問題根本不存在,是樓主沒有設置好PCON寄存器。這是用STC8H3K48S2在官方例程基礎上改寫的測試程序 ...

你這里用到了一個uint num=9990,這樣初始化就是9990,和我的情況是不一樣的,我如果寫成uchar ccapcounter=7,那會不會從現在歸零的情況0變成7?我認為樓上的回復有道理,我應該修改start A51這個文件,防止喚醒后變量被重新初始化。
作者: 千早愛音愛玩51    時間: 2025-7-9 00:16
lzuoxin 發表于 2025-7-6 13:32
進入休眠模式不變,掉電斷電會丟失的。

51掉電模式就是休眠模式,翻譯的問題,這個模式下cpu和片內外設都斷電,但ram不會斷電,可以保持數據。
作者: 千早愛音愛玩51    時間: 2025-7-9 00:19
WL0123 發表于 2025-7-6 14:55
樓主說的問題根本不存在,是樓主沒有設置好PCON寄存器。這是用STC8H3K48S2在官方例程基礎上改寫的測試程序 ...

不過你這里先讓CPU進入IDLE,再進入PD的方案,我會試試的,我現在是直接進入PD
作者: WL0123    時間: 2025-7-9 10:27
千早愛音愛玩51 發表于 2025-7-9 00:14
你這里用到了一個uint num=9990,這樣初始化就是9990,和我的情況是不一樣的,我如果寫成uchar ccapcount ...

初始化num可以是4位任意數,設9990只不過是驗證一下溢出后歸0,與數據能不能保持毫無關聯。
作者: coody_sz    時間: 2025-7-9 11:21
如果是STC的MCU,則進入掉電(睡眠)模式,只要電源正常供給,則內部所有的寄存器、內存數據都保持原樣,包括所有的IO設置和輸出都不改變。如果你發現改變了,則請檢查電源、程序。
作者: wufa1986    時間: 2025-7-9 11:46
你對單片機理解不夠深刻,51不存在這個問題,STM32有一種休眠模式才是重新運行
作者: a399288395    時間: 2025-7-16 08:10
只是DIY玩還是準備商用, 商用 不需要單片機; 有專門的單芯片;可以做按鍵換擋和鋰電池充放電;成本比單片機低得多;  如果是DIY;像STC 51 單片機 有掉電模式和低功耗模式; 不管哪種模式,存儲器中的數據都不會丟失;保持掉電前的狀態。
作者: Y_G_G    時間: 2025-7-16 12:39
1,SRAM在休眠后喚醒,在不掉電的情況下,它的值是不變的
2,我認為CCAP的值也是不變的,可能是你程序的問題
3,在這個應用中,沒有必要用到EEPROM,有種沒苦硬吃的感覺
4,14#已經說過了,如果是產品,用不到8051單片機的,有專門風扇芯片,如果是要更高級的功能,比如電量顯示,支持快充之類的,可以用一個OTP單片機,那玩意便宜
作者: lqb781101    時間: 2025-7-19 18:57
只要芯片電源引腳有電,SRAM的值不會掉的
作者: powerdruy    時間: 2025-7-23 16:53
deepsleep和standby是兩個模式




歡迎光臨 (http://m.zg4o1577.cn/bbs/) Powered by Discuz! X3.1
主站蜘蛛池模板: 欧美专区在线观看 | 黄色1级视频 | www.av在线 | 亚洲精品乱码久久久久 | 福利小视频在线观看 | 成人午夜在线观看 | 国产美女av | 久久夜色精品国产欧美乱极品 | 中文字幕在线观看免费视频 | 激情久久久 | 国产不卡在线 | 免费午夜视频 | 91精品国产成人观看 | 中文字幕在线视频观看 | 日本国产在线观看 | 日韩中文字幕视频 | www.久久久 | 欧美日韩综合在线 | 欧美黄色一级视频 | 亚洲午夜精品一区二区三区 | 四虎精品视频 | 亚洲视频免费看 | 日日夜夜精品 | 国产福利91 | 国产伦理一区二区 | 欧美一级欧美三级在线观看 | 日韩一区不卡 | 色多多视频在线观看 | 在线视频亚洲 | 成人毛片网 | 日日干av | 五月婷婷色综合 | a级黄毛片 | 日本亚洲欧美 | 国产乱码精品一品二品 | 一区二区三区四区在线视频 | 青青草福利视频 | 日韩成人免费 | 中文字幕av一区二区 | 懂色av成人一区二区三区 | 亚洲激情成人 |