找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 11920|回復(fù): 10
收起左側(cè)

怎樣使單片機(jī)程序斷電保留上次的數(shù)據(jù)?

  [復(fù)制鏈接]
回帖獎(jiǎng)勵(lì) 20 黑幣 回復(fù)本帖可獲得 5 黑幣獎(jiǎng)勵(lì)! 每人限 1 次
ID:263911 發(fā)表于 2018-4-20 22:42 | 顯示全部樓層 |閱讀模式
設(shè)計(jì)一個(gè)車速里程的程序,每次斷電后沒(méi)能留下上次走的路程 請(qǐng)問(wèn)怎么在程序里加個(gè)斷電保留數(shù)據(jù)的程序代碼?知道用at24c02,但不會(huì)編,求幫助sbit sda = P2^0;
sbit scl = P2^1;
  1. #include <reg52.h>                 //調(diào)用單片機(jī)頭文件
  2. #define uchar unsigned char  //無(wú)符號(hào)字符型 宏定義        變量范圍0~255
  3. #define uint  unsigned int         //無(wú)符號(hào)整型 宏定義        變量范圍0~65535

  4. uchar t1_num,t2_num;   //計(jì)時(shí)間中斷的次數(shù)
  5. unsigned long speed1,juli,time2;
  6. float f_hz        ,speed_km,speed_m;  //dlaout time1        ,speed_km,speed_m;
  7. uchar TH11,TL11;
  8. uchar flag_en;         //開(kāi)始計(jì)算速度使能
  9. uchar flag_stop_en;    //要確定車子是否停下了
  10. uint juli_s;               //每秒走的距離
  11. uint juli_z;           //總路程
  12. float zhijing = 0.55;  //直徑 0.55M
  13. bit flag_1s = 1;           //1s
  14. long zong_lc;          //總量程
  15. uchar flag_200ms;
  16. uint sudu;            //定義速度的變量
  17. uint bj_sudu = 20;           //報(bào)警速度


  18. //這三個(gè)引腳參考資料
  19. sbit rs=P2^6;               //寄存器選擇信號(hào) H:數(shù)據(jù)寄存器          L:指令寄存器
  20. sbit rw=P2^5;               //寄存器選擇信號(hào) H:數(shù)據(jù)寄存器          L:指令寄存器
  21. sbit e =P2^7;               //片選信號(hào)   下降沿觸發(fā)

  22. uchar code table_num[]="0123456789abcdefg";
  23. uchar i;

  24. sbit beep = P1^5;   //蜂鳴器IO口定義

  25. /******************1ms 延時(shí)函數(shù)*******************/
  26. void delay_1ms(uint q)
  27. {
  28.         uint i,j;
  29.         for(i=0;i<q;i++)
  30.                 for(j=0;j<120;j++);
  31. }


  32. /********************************************************************
  33. * 名稱 : delay_uint()
  34. * 功能 : 小延時(shí)。
  35. * 輸入 : 無(wú)
  36. * 輸出 : 無(wú)
  37. ***********************************************************************/
  38. void delay_uint(uint q)
  39. {
  40.         while(q--);
  41. }

  42. /********************************************************************
  43. * 名稱 : write_com(uchar com)
  44. * 功能 : 1602命令函數(shù)
  45. * 輸入 : 輸入的命令值
  46. * 輸出 : 無(wú)
  47. ***********************************************************************/
  48. void write_com(uchar com)
  49. {
  50.         i=0;
  51.         e=0;
  52.         rs=0;
  53.         rw=0;
  54.         P0=com;
  55.         delay_uint(25);
  56.         e=1;
  57.         delay_uint(50);
  58.         e=0;
  59. }

  60. /********************************************************************
  61. * 名稱 : write_data(uchar dat)
  62. * 功能 : 1602寫(xiě)數(shù)據(jù)函數(shù)
  63. * 輸入 : 需要寫(xiě)入1602的數(shù)據(jù)
  64. * 輸出 : 無(wú)
  65. ***********************************************************************/
  66. void write_data(uchar dat)
  67. {
  68.         i=0;
  69.         e=0;
  70.         rs=1;
  71.         rw=0;
  72.         P0=dat;
  73.         delay_uint(25);
  74.         e=1;
  75.         delay_uint(50);
  76.         e=0;        
  77. }

  78. /********************************************************************
  79. * 名稱 : write_sfm2(uchar hang,uchar add,uchar date)
  80. * 功能 : 顯示2位十進(jìn)制數(shù),如果要讓第一行,第五個(gè)字符開(kāi)始顯示"23" ,調(diào)用該函數(shù)如下
  81.                   write_sfm1(1,5,23)
  82. * 輸入 : 行,列,需要輸入1602的數(shù)據(jù)
  83. * 輸出 : 無(wú)
  84. ***********************************************************************/
  85. void write_sfm2(uchar hang,uchar add,uint date)
  86. {
  87.         if(hang==1)   
  88.                 write_com(0x80+add);
  89.         else
  90.                 write_com(0x80+0x40+add);
  91.            write_data(0x30+date/10%10);
  92.            write_data(0x30+date%10);        
  93. }

  94. /********************************************************************
  95. * 名稱 : write_sfm4(uchar hang,uchar add,uchar date)
  96. * 功能 : 顯示2位十進(jìn)制數(shù),如果要讓第一行,第五個(gè)字符開(kāi)始顯示"23" ,調(diào)用該函數(shù)如下
  97.                   write_sfm1(1,5,23)
  98. * 輸入 : 行,列,需要輸入1602的數(shù)據(jù)
  99. * 輸出 : 無(wú)
  100. ***********************************************************************/
  101. void write_sfm4(uchar hang,uchar add,uint date)
  102. {
  103.         if(hang==1)   
  104.                 write_com(0x80+add);
  105.         else
  106.         write_com(0x80+0x40+add);
  107.    write_data(0x31+date/100000%10);
  108.         write_data(0x33+date/10000%10);
  109.         write_data(0x36+date/1000%10);
  110.         write_data('.');        
  111.         write_data(0x35+date/100%10);        
  112.         write_data(0x33+date/10%10);
  113.         write_data(0x32+date%10);        
  114.         write_data('k');        
  115.         write_data('m');        
  116. }

  117. /********************************************************************
  118. * 名稱 : write_string(uchar hang,uchar add,uchar *p)
  119. * 功能 : 改變液晶中某位的值,如果要讓第一行,第五個(gè)字符開(kāi)始顯示"ab cd ef" ,調(diào)用該函數(shù)如下
  120.                   write_string(1,5,"ab cd ef;")
  121. * 輸入 : 行,列,需要輸入1602的數(shù)據(jù)
  122. * 輸出 : 無(wú)
  123. ***********************************************************************/
  124. void write_string(uchar hang,uchar add,uchar *p)
  125. {
  126.         if(hang==1)   
  127.                 write_com(0x80+add);
  128.         else
  129.                 write_com(0x80+0x40+add);
  130.                 while(1)
  131.                 {
  132.                         if(*p == '\0')  break;
  133.                         write_data(*p);
  134.                         p++;
  135.                 }        
  136. }

  137. /********************************************************************
  138. * 名稱 : init_1602()
  139. * 功能 : 初始化1602液晶
  140. * 輸入 : 無(wú)
  141. * 輸出 : 無(wú)
  142. ***********************************************************************/
  143. void init_1602()      //1602初始化
  144. {
  145.         write_com(0x38);
  146.         write_com(0x0c);
  147.         write_com(0x06);
  148.         delay_uint(1000);
  149.         write_string(1,0,"sd:00km/h       ");               
  150.         write_string(2,0,"lc:00.00km      ");        
  151. }

  152. /***********外部中斷0初始化程序****************/
  153. void init_int0()
  154. {
  155.         EX0=1;                          //允許外部中斷0中斷
  156.         EA=1;                           //開(kāi)總中斷
  157.         IT0 = 1;                   //外部中斷0負(fù)跳變中斷
  158. }


  159. /*************定時(shí)器0初始化程序***************/
  160. void time_init()          //定時(shí)器0初始化程序
  161. {
  162.         EA   = 1;                   //開(kāi)總中斷
  163.         TMOD = 0X11;          //定時(shí)器0、工作方式1
  164.         ET0  = 1;                  //開(kāi)定時(shí)器0中斷
  165.         TR0  = 1;                  //允許定時(shí)器0定時(shí)
  166.         ET1  = 1;                  //開(kāi)定時(shí)器1中斷
  167.         TR1  = 1;                  //允許定時(shí)器1定時(shí)
  168. }

  169. /***********計(jì)算速度函數(shù)**************/
  170. void menu_speed()          //計(jì)算速度函數(shù)
  171. {
  172.         static uchar value,value1;
  173.         if(flag_1s == 1)   
  174.                 {        
  175.                         flag_1s = 0;                 
  176.                         if(flag_en == 0)
  177.                         {
  178.                                 value ++;
  179.                                 if(value >= 3)        //2秒
  180.                                 {        
  181.                                         speed_km = 0;  //速度為0
  182.                                         sudu = (uint)speed_km;        
  183.                                         value = 0;                                
  184.                                 }
  185.                         }
  186.                         if((flag_en == 1))
  187.                         {        
  188.                                 value = 0;               
  189.                                 flag_en = 0;         
  190.                                  //1s = 1 / 1000000us;          // 1m/s=0.001km除以1/3600h=3.6km/h                        
  191.                                 f_hz = 1000000 / (t2_num * 65536.0 + TH11 * 256 + TL11);  //算出來(lái)就是秒
  192.                                 t2_num = 0;        //把變量清零
  193.                                 TH11 = 0;
  194.                                 TL11 = 0;                                          
  195.                                 speed_m = f_hz * zhijing * 3.14  ;        //算出來(lái)的是m/s
  196.                                 juli_z = (juli_z + (uint)speed_m) ;        //總路程m        
  197.                                 speed_km = speed_m * 3.6 ;        //(帶個(gè)小數(shù)點(diǎn)) km/s               
  198.                            sudu = (uint)speed_km;
  199.                                 if(sudu >= 99)
  200.                                         sudu = 99;
  201.                                 zong_lc += speed_m;
  202.                                 value1++;
  203.                                 if(value1 >= 20)
  204.                                 {
  205.                                         value1 = 0;
  206.                                 }
  207.                         }               

  208.                         write_sfm2(1,3,sudu);               
  209.                         write_sfm4(2,3,juli_z);               
  210.         }
  211. }


  212. /****************報(bào)警函數(shù)***************/
  213. void clock_h_l()
  214. {
  215.         static uchar value;           
  216.         if((sudu >= bj_sudu))
  217.         {
  218.                 value ++;  //消除實(shí)際距離在設(shè)定距離左右變化時(shí)的干擾
  219.                 if(value > 5)
  220.                 {
  221.                         beep = ~beep;           //蜂鳴器報(bào)警                        
  222.                 }        
  223.         }
  224.         else
  225.         {
  226.                 beep = 1;        
  227.         }                        
  228. }


  229. /******************主程序**********************/           
  230. void main()
  231. {
  232.         beep = 0;
  233.         delay_1ms(200) ;
  234.         P0 = P1 = P2 = P3 = 0xff;  //IO口初始為電平        
  235.         init_1602();      //1602初始化
  236.         init_int0();
  237.         time_init();          //定時(shí)器0初始化程序
  238.         while(1)
  239.         {         
  240.                 if(flag_200ms == 1)
  241.                 {
  242.                         flag_200ms = 0;
  243.                         menu_speed();          //計(jì)算速度函數(shù)
  244.                         clock_h_l();        //報(bào)警函數(shù)
  245.                 }
  246.         }
  247. }


  248. /*********************外部中斷0中斷服務(wù)程序************************/
  249. void int0() interrupt 0
  250. {
  251.         static uchar value;
  252.         switch(value)
  253.         {
  254.                 case 0:
  255.                         t1_num = 0;                 //第一次就把變量清零
  256.                         TH1 = 0;
  257.                         TL1 = 0;
  258.                         break;
  259.                 case 1:
  260.                                 t2_num = t1_num;  //保存
  261.                                 TH11 = TH1;
  262.                                 TL11 = TL1;
  263.                                 flag_en = 1;
  264.                         break;
  265.         }               
  266.         value ++;
  267.         if(value >= 2)
  268.                 value =0;
  269.         /************
  270.                 2.1   16.6
  271.                 2          15.8
  272.                 1.9   15.0
  273.         ************/
  274. }

  275. /*************定時(shí)器0中斷服務(wù)程序***************/
  276. void time0_int() interrupt 1
  277. {        
  278.         static uchar value;
  279.         TH0 = 0x3c;
  280.         TL0 = 0xb0;     // 50ms
  281.         value++;
  282.         if(value % 4 == 0)
  283.                 flag_200ms = 1;

  284.         if(value >= 20)  //1秒   才是一秒鐘的速度
  285.         {
  286.                 value = 0;
  287.                 flag_1s = 1;
  288.         }
  289. }

  290. /*************定時(shí)器1中斷服務(wù)程序***************/
  291. void time1_int() interrupt 3
  292. {
  293.         t1_num++;
  294. }
復(fù)制代碼




回復(fù)

使用道具 舉報(bào)

ID:123289 發(fā)表于 2018-4-21 06:09 | 顯示全部樓層

回帖獎(jiǎng)勵(lì) +5 黑幣

在電源電路上做文章:
要點(diǎn):整流電路分兩節(jié),用整流二極隔開(kāi)。
最前級(jí)濾波電容要小,如1uF就好了,并做一個(gè)檢測(cè)電壓的電路,檢測(cè)它是否掉電,掉電時(shí)產(chǎn)生INT中斷,提醒你保存需要保存的數(shù)據(jù)。
后一級(jí)濾波電容要大,如1000uF,這樣當(dāng)前級(jí)失電時(shí),后級(jí)會(huì)保持有電一段時(shí)間,二極管能保證最前級(jí)無(wú)電時(shí),后級(jí)的電不會(huì)向前放電。這樣你就有充分的時(shí)間來(lái)做數(shù)據(jù)保存了。
我做的產(chǎn)品都是這樣做的,而且還做了數(shù)據(jù)是否寫(xiě)錯(cuò)的檢驗(yàn),這是另一個(gè)課題了,不在此描述了。如果驅(qū)動(dòng)電路耗電大,要做處理。
明白這個(gè)道理后,相信你也會(huì)想出招數(shù)了。要點(diǎn):讓CPU及存儲(chǔ)器部分,在失電后,能保持有電一段時(shí)間,并能檢測(cè)到失電。!

評(píng)分

參與人數(shù) 1黑幣 +5 收起 理由
帥到爆炸 + 5 贊一個(gè)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:312823 發(fā)表于 2018-4-21 08:02 | 顯示全部樓層
一般常用的方法是采用eeprom實(shí)時(shí)保存你剛刷新的數(shù)據(jù),這樣任何時(shí)候一斷電都能再找回來(lái)
回復(fù)

使用道具 舉報(bào)

ID:311504 發(fā)表于 2018-5-5 15:25 | 顯示全部樓層
請(qǐng)問(wèn)計(jì)算速度的函數(shù)怎么理解?
回復(fù)

使用道具 舉報(bào)

ID:316332 發(fā)表于 2018-5-5 16:52 | 顯示全部樓層
不一定非用at24c02,單片機(jī)片內(nèi)的EEPROM存儲(chǔ)器也可以
回復(fù)

使用道具 舉報(bào)

ID:307391 發(fā)表于 2018-5-6 08:52 | 顯示全部樓層
EEPROM,即可
回復(fù)

使用道具 舉報(bào)

ID:323199 發(fā)表于 2018-5-6 09:15 | 顯示全部樓層
eeprom
回復(fù)

使用道具 舉報(bào)

ID:343102 發(fā)表于 2018-7-5 22:05 | 顯示全部樓層
現(xiàn)在的單片機(jī)芯片大多自帶EEPROM,還有低壓檢測(cè)功能,可以利用此功能在斷電時(shí)保存數(shù)據(jù)。
EEPROM有可擦除最大次數(shù),雖然這個(gè)數(shù)字看著不小,但對(duì)于程序來(lái)說(shuō)并不大,比如EEPROM為100萬(wàn)次,如果我們以0.1秒的間隔寫(xiě)入數(shù)據(jù),則只能維持1000000*0.1/3600=27.78小時(shí),也就是一天多就可以超出其最大壽命次數(shù),所以不能采用即時(shí)刷新的方法。

評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 回帖助人的獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:308437 發(fā)表于 2018-7-5 22:24 | 顯示全部樓層

現(xiàn)在的單片機(jī)芯片大多自帶EEPROM,還有低壓檢測(cè)功能,可以利用此功能在斷電時(shí)保存數(shù)據(jù)。
EEPROM有可擦除最大次數(shù),雖然這個(gè)數(shù)字看著不小,但對(duì)于程序來(lái)說(shuō)并不大,比如EEPROM為100萬(wàn)次,如果我們以0.1秒的間隔寫(xiě)入數(shù)據(jù),則只能維持1000000*0.1/3600=27.78小時(shí),也就是一天多就可以超出其最大壽命次數(shù),所以不能采用即時(shí)刷新的方法!蓖膺@個(gè)觀點(diǎn)。設(shè)置刷新時(shí)間,或者低壓檢測(cè),要斷電的時(shí)候保存數(shù)據(jù)

評(píng)分

參與人數(shù) 1黑幣 +60 收起 理由
admin + 60 回帖助人的獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:365986 發(fā)表于 2018-7-6 00:01 | 顯示全部樓層
STC單片機(jī)內(nèi)部有EEPROM?梢远x一個(gè)在EEPROM中的變量,將此次設(shè)置的內(nèi)容存入EEPROM,下次上電直接讀取就好。
回復(fù)

使用道具 舉報(bào)

ID:365824 發(fā)表于 2018-7-6 01:20 | 顯示全部樓層
用單片機(jī)的ROM區(qū)可以儲(chǔ)存,運(yùn)用指針指定儲(chǔ)存位置
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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