1024手机基地看电影,午夜福利视频导航,国产精品福利在线一区,亚洲欧美日韩另类成人,在线观看午夜日本理论片,成年超爽免费网站,国产精品成人免费,精品动作一级毛片,成人免费观看网站,97精品伊人久久大香蕉

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

DS1302掉電不丟失時(shí)間單片機(jī)程序編寫問題

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
本帖最后由 jianwei2030 于 2017-9-3 21:12 編輯

自己做了一個(gè)萬年歷時(shí)鐘,利用STC15W408AS單片機(jī),時(shí)鐘芯片采用DS1302。當(dāng)前自己參考網(wǎng)上寫了時(shí)間讀取的程序,在實(shí)驗(yàn)板走時(shí)正常,但是斷電再上電后無法保存時(shí)間,程序在首次上電后會(huì)初始化一個(gè)固定的時(shí)間,每次都得自己重新調(diào)時(shí)。看到網(wǎng)上有種說法是給1302寫入標(biāo)志位,每次系統(tǒng)上電后檢測這個(gè)標(biāo)志位,如果能夠檢測到就不初始化時(shí)間,直接讀取;如果檢測不到標(biāo)志位就初始化。但是按照這種方法試過后仍然不見效果,請大家?guī)兔纯次疫@程序該怎么修改合適?

電路部分:

以下是我的程序:
1302部分:
  1. #include<STC15W.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. /*  宏定義寫DS1302的地址  */
  5. #define write_sec_add            0x80        //秒數(shù)據(jù)地址    1000 0000
  6. #define write_min_add            0x82        //分?jǐn)?shù)據(jù)地址    1000 0010
  7. #define write_hr_add            0x84        //時(shí)數(shù)據(jù)地址    1000 0100
  8. #define write_week_add            0x86        //星期數(shù)據(jù)地址    1000 0110
  9. #define write_month_add            0x88        //月數(shù)據(jù)地址    1000 1000
  10. #define write_day_add            0x8a        //日數(shù)據(jù)地址    1000 1010
  11. #define write_year_add            0x8c        //年數(shù)據(jù)地址    1000 1100
  12. #define write_control_add        0x8e        //控制數(shù)據(jù)地址    1000 1110
  13. #define write_charger_add        0x90         //可編程涓流充電地址 1001 0000            
  14. #define write_clkburst_add        0xbe        //時(shí)鐘脈沖串地址
  15. #define write_RAM0_add            0xc0        //RAM0寄存器寫地址     1100 0000
  16. /*  宏定義讀DS1302的地址  */
  17. #define read_sec_add            0x81        //秒數(shù)據(jù)地址    1000 0001
  18. #define read_min_add            0x83        //分?jǐn)?shù)據(jù)地址    1000 0011
  19. #define read_hr_add                0x85        //時(shí)數(shù)據(jù)地址    1000 0101
  20. #define read_week_add            0x87        //星期數(shù)據(jù)地址    1000 0111
  21. #define read_month_add            0x89        //月數(shù)據(jù)地址    1000 1001
  22. #define read_day_add            0x8b        //日數(shù)據(jù)地址    1000 1011
  23. #define read_year_add            0x8d        //年數(shù)據(jù)地址    1000 1101
  24. #define read_control_add        0x8f        //控制數(shù)據(jù)地址  1000 1111
  25. #define read_charger_add        0x91         //可編程涓流充電地址  1001 0001              
  26. #define read_clkburst_add        0xbe        //時(shí)鐘脈沖串地址
  27. #define read_RAM0_add            0xc1        //RAM0寄存器讀地址      1100 0001

  28. //#define P2M1 = 0x00;    //0000 0000               
  29. //#define P2M0 = 0x04;    //0000 0100
  30. uchar sec,min,hr,week,mouth,day,year,ram_data;

  31. sbit sclk=P2^1;        
  32. sbit io=P2^2;        
  33. sbit ce=P2^3;

  34. void write1302_time(uchar address,uchar dat)  //寫入數(shù)據(jù)給1302
  35. {
  36.     uchar i;
  37.     ce=0;     //禁止讀寫數(shù)據(jù)
  38.     sclk=0;   
  39.     for(i=0;i<8;i++)    //寫地址
  40.     {
  41.       ce=1;     //允許讀寫數(shù)據(jù)
  42.       sclk=0;
  43.       io=address&0x01;  
  44.       address>>=1;
  45.       sclk=1;
  46.     }
  47.     for(i=0;i<8;i++)    //寫數(shù)據(jù)
  48.     {
  49.       ce=1;    //允許讀寫數(shù)據(jù)
  50.       sclk=0;
  51.       io=dat&0x01;
  52.       dat>>=1;
  53.       sclk=1;
  54.     }
  55.     ce=0;
  56. }

  57. uchar read1302_time(uchar address) //從1302讀取時(shí)間數(shù)據(jù)
  58. {
  59.     uchar i,num;
  60.     ce=0;   //禁止讀寫數(shù)據(jù)
  61.     for(i=0;i<8;i++)
  62.     {
  63.       ce=1;
  64.       sclk=0;
  65.       io=address&0x01;
  66.       address>>=1;
  67.       sclk=1;
  68.     }
  69.     for(i=0;i<8;i++)
  70.     {
  71.       if(io==1)
  72.         num=num|0x80;
  73.       else
  74.         num=num|0x00;

  75.       sclk=1;
  76.       num>>=1;
  77.       sclk=0;
  78.     }
  79.     ce=0;
  80.     return num;
  81. }

  82. void init_1302() //初始化函數(shù) 設(shè)置時(shí)間
  83. {
  84.     read_ram_data = read1302_time(read_RAM0_add);
  85.        if(rread_ram_data!=0xf0)
  86.     {
  87.         write1302_time(0x8e,0x00);  //保護(hù)取消,可以進(jìn)行讀寫操作
  88.         write1302_time(write_sec_add,0x00);//寫入初始秒時(shí)間 0101 0110
  89.         write1302_time(write_min_add,0x35);//寫入初始分時(shí)間 0101 0110
  90.         write1302_time(write_hr_add,0x22); //寫入初始時(shí)時(shí)間 0101 0110
  91.         write1302_time(write_week_add,0x06); //寫入初始周時(shí)間 0101 0110
  92.         write1302_time(write_month_add,0x08); //寫入初始月時(shí)間 0101 0110
  93.         write1302_time(write_day_add,0x12); //寫入初始日時(shí)間 0101 0110
  94.         write1302_time(write_year_add,0x17); //寫入初始年時(shí)間 0101 0110
  95.         write1302_time(0x90,0xa5);    //使能涓流充電,  1010 0101
  96.         write1302_time(write_RAM0_add,0xf0); //往RAM寄存器中寫入0xf0數(shù)據(jù),因?yàn)镽AM有掉電丟失特點(diǎn),所以進(jìn)入初始化函數(shù)的時(shí)候首先判斷這個(gè)寄存器是否還有數(shù)據(jù)
  97.         write1302_time(0x8e,0x80);   //保護(hù)啟動(dòng),禁止對(duì)1302寫操作
  98.     }
  99. }
  100. void xianshi_data() //將從1302讀出的二進(jìn)制數(shù)據(jù)轉(zhuǎn)換為十進(jìn)制
  101. {
  102.     uchar read_sec,    read_min, read_hr, read_week, read_mouth, read_day, read_year;

  103.     read_sec = read1302_time(read_sec_add);       //從“read1302_time”函數(shù)取得返回值num的數(shù)據(jù)
  104.         sec = ((read_sec&0x70)>>4)*10+(read_sec&0x0f); //十進(jìn)制“秒”

  105.     read_min = read1302_time(read_min_add);
  106.         min = ((read_min&0x70)>>4)*10+(read_min&0x0f); //十進(jìn)制“分”

  107.     read_hr = read1302_time(read_hr_add);
  108.         hr = ((read_hr&0x70)>>4)*10+(read_hr&0x0f);     //十進(jìn)制“時(shí)”

  109.     read_week = read1302_time(read_week_add);
  110.         week = ((read_week&0x70)>>4)*10+(read_week&0x0f);  //十進(jìn)制“周”

  111.     read_day = read1302_time(read_day_add);
  112.         day = ((read_day&0x70)>>4)*10+(read_day&0x0f);    //十進(jìn)制“日”

  113.     read_mouth = read1302_time(read_month_add);
  114.         mouth = ((read_mouth&0x70)>>4)*10+(read_mouth&0x0f); //十進(jìn)制“月”

  115.     read_year = read1302_time(read_year_add);
  116.         year = ((read_year&0x70)>>4)*10+(read_year&0x0f);    //十進(jìn)制“年”
  117. }
復(fù)制代碼


主函數(shù)部分:
  1. #include<STC15W.h>
  2. #include"1302.h"
  3. #include"18B20.h"
  4. #include"display.h"
  5. #include"keyboard.h"
  6. #define uchar unsigned char
  7. #define uint unsigned int

  8. //#define  P2M1_set  0x00    //設(shè)置P2口工作模式   0000 0000
  9. //#define  P2M0_set  0x0d //設(shè)置P2口工作模式   0000 1110
  10. uchar num;
  11. /*************************延時(shí)函數(shù)*************************/
  12. void delay(uint a)         // 1ms延時(shí)程序(12MHz 10倍于51單片機(jī)速度時(shí))
  13. {
  14.     uint i;
  15.     while(--a != 0)
  16.     {
  17.         for(i = 0;i < 600;i++);
  18.     }                           
  19. }
  20. /***************************************初始化IO口狀態(tài)**************************************/
  21. //void IO_init(void)
  22. //{
  23. //P2M1 = P2M1_set;
  24. //P2M0 = P2M0_set;
  25. //}
  26. /**************************************外部中斷INT2初始化函數(shù) **************************************/
  27. void INT2_init()
  28. {      
  29.     INT_CLKO |=    0x10;
  30.     EA = 1;
  31. }

  32. void main()
  33. {   
  34.     INT2_init();
  35. //    IO_init();
  36. //    read_ram();
  37.     init_1302();
  38.     init_18b20();
  39.     while(1)
  40.     {
  41.         display_service();
  42.         display_qiehuan();
  43.     }
  44. }
復(fù)制代碼

這是網(wǎng)上找到的別人的回答:
https://zhidao.baidu.com/question/345394758.html



分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏3 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:82765 發(fā)表于 2017-9-2 21:31 | 只看該作者
提示: 作者被禁止或刪除 內(nèi)容自動(dòng)屏蔽
回復(fù)

使用道具 舉報(bào)

板凳
ID:230544 發(fā)表于 2017-9-2 23:08 | 只看該作者
你可以修改一下你的初始化函數(shù),DS1302里面不是有好多空著的寄存器嘛,你可以先檢測某一個(gè)寄存器是否為0,為零就初始化,初始化完畢后給這個(gè)寄存器寫1,這樣就可以了

評(píng)分

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

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

地板
ID:135636 發(fā)表于 2017-9-3 20:09 | 只看該作者
黑暗人才 發(fā)表于 2017-9-2 23:08
你可以修改一下你的初始化函數(shù),DS1302里面不是有好多空著的寄存器嘛,你可以先檢測某一個(gè)寄存器是否為0, ...

網(wǎng)上的說法也是這樣做,初始化時(shí)在1302的ram中寫入一個(gè)數(shù)值,以后每次上電都檢測這個(gè)數(shù)值,如果檢測到就不執(zhí)行初始化程序,檢測不到就執(zhí)行初始化程序。但是我想知道怎么寫這個(gè)檢測程序。
回復(fù)

使用道具 舉報(bào)

5#
ID:135636 發(fā)表于 2017-9-3 20:14 | 只看該作者
cjjcjj1 發(fā)表于 2017-9-2 21:31
你好!
1、要想斷電時(shí)鐘繼續(xù)走時(shí),1302要加后備電池
2、斷電后,重啟,時(shí)鐘恢復(fù) 17年8月12日

后備電池是有加3V紐扣電池的;刪掉初始化函數(shù)后第一次上電就什么也不顯示了,我希望第一次上電時(shí)顯示一個(gè)初始時(shí)間,用戶在這個(gè)時(shí)間的基礎(chǔ)上再修改。
回復(fù)

使用道具 舉報(bào)

6#
ID:99130 發(fā)表于 2017-9-4 22:49 | 只看該作者
屏蔽掉初始化
回復(fù)

使用道具 舉報(bào)

7#
ID:158667 發(fā)表于 2017-9-5 10:48 | 只看該作者
電路沒問題,不同公司的1302驅(qū)動(dòng)方法上可能存在不同,我也遇到過同樣的問題,換個(gè)1302就好了
回復(fù)

使用道具 舉報(bào)

8#
ID:135636 發(fā)表于 2017-9-7 21:53 | 只看該作者
mengx 發(fā)表于 2017-9-5 10:48
電路沒問題,不同公司的1302驅(qū)動(dòng)方法上可能存在不同,我也遇到過同樣的問題,換個(gè)1302就好了

換過了,前后都是用達(dá)拉斯的芯片
回復(fù)

使用道具 舉報(bào)

9#
ID:135636 發(fā)表于 2017-9-7 21:56 | 只看該作者
黑暗人才 發(fā)表于 2017-9-2 23:08
你可以修改一下你的初始化函數(shù),DS1302里面不是有好多空著的寄存器嘛,你可以先檢測某一個(gè)寄存器是否為0, ...

網(wǎng)上也是這么說的,我是檢測1302內(nèi)部的31字節(jié)的第一位,初始化時(shí)給這一位寫入一個(gè)數(shù)據(jù),再上電時(shí)讀取這一位是不是之前寫入的值,但是根據(jù)網(wǎng)上的程序修改沒有效果。
回復(fù)

使用道具 舉報(bào)

10#
ID:135636 發(fā)表于 2017-10-8 15:35 | 只看該作者
我修改了上電檢測部分的程序(如下),
思路是:上電后檢測RAM中存儲(chǔ)的數(shù)據(jù)十位是否為7,如果是則跳過初始化程序(什么也不執(zhí)行),如果不是則執(zhí)行初始化子程序
可是不管我怎么修改,修改后的時(shí)間就是無法保存,每次上電后依然是初始化的時(shí)間,要怒了。。。

void init_1302() //初始化函數(shù) 設(shè)置時(shí)間
{
                write1302_time(write_control_add,0x00);  //保護(hù)取消,可以進(jìn)行讀寫操作
                write1302_time(write_sec_add,0x30);//寫入初始秒時(shí)間 0101 0110
                write1302_time(write_min_add,0x05);//寫入初始分時(shí)間 0101 0110
                write1302_time(write_hr_add,0x21); //寫入初始時(shí)時(shí)間 0101 0110
                write1302_time(write_week_add,0x07); //寫入初始周時(shí)間 0101 0110
                write1302_time(write_month_add,0x09); //寫入初始月時(shí)間 0101 0110
                write1302_time(write_day_add,0x03); //寫入初始日時(shí)間 0101 0110
                write1302_time(write_year_add,0x17); //寫入初始年時(shí)間 0101 0110
                write1302_time(write_RAM0_add,0x17); //往RAM寄存器中寫入0xf0數(shù)據(jù),因?yàn)镽AM有掉電丟失特點(diǎn),所以進(jìn)入初始化函數(shù)的時(shí)候首先判斷這個(gè)寄存器是否還有數(shù)據(jù)
                write1302_time(write_charger_add,0xab);        //使能涓流充電,兩個(gè)二極管+8k電阻  1010 1011
                write1302_time(write_control_add,0x80);   //保護(hù)啟動(dòng),禁止對(duì)1302寫操作
}

void ram_flag()
{
        read_ram_data = read1302_time(read_RAM0_add);                
        ram_data = ((read_ram_data&0x70)>>4)*10+(read_ram_data&0x0f);
        if((ram_data%10) == 7)
        {
                write1302_time(write_control_add,0x80);   //保護(hù)啟動(dòng),禁止對(duì)1302寫操作
        }
        else if((ram_data%10) != 7)
        {
                init_1302();
        }
}
回復(fù)

使用道具 舉報(bào)

11#
ID:140489 發(fā)表于 2017-10-10 15:58 | 只看該作者
jianwei2030 發(fā)表于 2017-9-7 21:53
換過了,前后都是用達(dá)拉斯的芯片

換進(jìn)口的DS1302,同樣的程序,進(jìn)口的芯片可以,有些國產(chǎn)的芯片就是不行
回復(fù)

使用道具 舉報(bào)

12#
ID:144936 發(fā)表于 2018-7-2 01:29 | 只看該作者
DS1302掉電后內(nèi)部RAM的值不等于3,可以判斷后初始化時(shí)間,然后標(biāo)記為3即可。

評(píng)分

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

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

13#
ID:362877 發(fā)表于 2018-7-2 09:40 | 只看該作者
你們也太厲害了吧
回復(fù)

使用道具 舉報(bào)

14#
ID:362877 發(fā)表于 2018-7-2 09:41 | 只看該作者

DS1302掉電后內(nèi)部RAM的值不等于3,可以判斷后初始化時(shí)間,然后標(biāo)記為3即可。
回復(fù)

使用道具 舉報(bào)

15#
ID:420015 發(fā)表于 2019-3-26 20:44 | 只看該作者
我還看到過說1302的vcc2連接一個(gè)10000uF的電容,就可以斷電也能繼續(xù)計(jì)時(shí),說再加一個(gè)write1302_time(0x90,0xa6);就可以
這個(gè)說法是真的嗎?

為什么我的板是連了一個(gè)10 0000uF的電容,試了,失敗了,還是說一定要加一個(gè)3v的備用電池才能做到斷電繼續(xù)計(jì)時(shí)?
回復(fù)

使用道具 舉報(bào)

16#
ID:716109 發(fā)表于 2020-3-30 18:50 | 只看該作者
我以上方法都試了都不行
回復(fù)

使用道具 舉報(bào)

17#
ID:47286 發(fā)表于 2020-3-30 20:48 | 只看該作者
不明白你說的不成都什么不成 也沒太看明白你要求什么 1302這東西 掉電就沒時(shí)間了 必須要重新寫入時(shí)間

往1302的RAM寫校驗(yàn)標(biāo)記是可以的 完全沒問題 我正在用 寫的是第一個(gè)地址 注意 因?yàn)?302是BCD格式寫入 如果你寫的值超過6位讀出來就只有6位 比如寫0xaa進(jìn)去出來是0x2a

如果你的板子沒設(shè)計(jì)后備電池 可以在供電線路上并聯(lián)一個(gè)電池 電池的正極串聯(lián)一個(gè)二極管 和后備電池意思一樣

如果是片子斷電后再上電 也不一定非要去讀1302 寫個(gè)預(yù)處理函數(shù) 在主循環(huán)的while之前執(zhí)行 只要是第一次上電 都先從1302讀時(shí)間到緩沖區(qū) 然后再到主循環(huán)里顯示 當(dāng)然 這樣做的前提是1302不能斷電 否則讀出來的肯定是錯(cuò)誤的時(shí)間 讀1302的RAM方法只是為了判斷是否執(zhí)行調(diào)表
回復(fù)

使用道具 舉報(bào)

18#
ID:65297 發(fā)表于 2020-3-30 21:30 | 只看該作者
軟件你已經(jīng)寫好了,而且是可以正常使用的,現(xiàn)在最簡單的方法就是用一個(gè)IO口來判斷是否需要初始化即可,
例如你的P55腳是空的,在初始化前面先判斷P55,是0的話初始化,是1就不初始化,你燒錄好程序,如果想要初始化就把P55接地再上電就會(huì)初始化了,不需要初始化時(shí)懸空即可,多簡單啊
回復(fù)

使用道具 舉報(bào)

19#
ID:316880 發(fā)表于 2020-3-30 23:51 | 只看該作者
這個(gè)問題啊,時(shí)間初始化是程序的問題,要設(shè)置一下那個(gè)什么命令,不太記得了,我DS1302,都是直接調(diào)用程序,改一下IO口就可以用了,你找的程序不對(duì),你這個(gè)是程序初始化的時(shí)候把時(shí)間給初始化了。
回復(fù)

使用道具 舉報(bào)

20#
ID:716109 發(fā)表于 2020-3-31 09:11 | 只看該作者
黑暗人才 發(fā)表于 2017-9-2 23:08
你可以修改一下你的初始化函數(shù),DS1302里面不是有好多空著的寄存器嘛,你可以先檢測某一個(gè)寄存器是否為0, ...

我是這樣檢測的,第一次上電后是我的初始化時(shí)間,但是第二次上電后時(shí)間從0開始,說明我的備用電源正常,應(yīng)為向存儲(chǔ)器寫的內(nèi)容沒有丟失,但是時(shí)間為啥不對(duì)呢,請問遇到過同類型的問題嗎,新手已被逼瘋。
回復(fù)

使用道具 舉報(bào)

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

本版積分規(guī)則

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

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

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