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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 15117|回復: 19
打印 上一主題 下一主題
收起左側

DS1302掉電不丟失時間單片機程序編寫問題

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

自己做了一個萬年歷時鐘,利用STC15W408AS單片機,時鐘芯片采用DS1302。當前自己參考網上寫了時間讀取的程序,在實驗板走時正常,但是斷電再上電后無法保存時間,程序在首次上電后會初始化一個固定的時間,每次都得自己重新調時。看到網上有種說法是給1302寫入標志位,每次系統上電后檢測這個標志位,如果能夠檢測到就不初始化時間,直接讀取;如果檢測不到標志位就初始化。但是按照這種方法試過后仍然不見效果,請大家幫忙看看我這程序該怎么修改合適?

電路部分:

以下是我的程序:
1302部分:
  1. #include<STC15W.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. /*  宏定義寫DS1302的地址  */
  5. #define write_sec_add            0x80        //秒數據地址    1000 0000
  6. #define write_min_add            0x82        //分數據地址    1000 0010
  7. #define write_hr_add            0x84        //時數據地址    1000 0100
  8. #define write_week_add            0x86        //星期數據地址    1000 0110
  9. #define write_month_add            0x88        //月數據地址    1000 1000
  10. #define write_day_add            0x8a        //日數據地址    1000 1010
  11. #define write_year_add            0x8c        //年數據地址    1000 1100
  12. #define write_control_add        0x8e        //控制數據地址    1000 1110
  13. #define write_charger_add        0x90         //可編程涓流充電地址 1001 0000            
  14. #define write_clkburst_add        0xbe        //時鐘脈沖串地址
  15. #define write_RAM0_add            0xc0        //RAM0寄存器寫地址     1100 0000
  16. /*  宏定義讀DS1302的地址  */
  17. #define read_sec_add            0x81        //秒數據地址    1000 0001
  18. #define read_min_add            0x83        //分數據地址    1000 0011
  19. #define read_hr_add                0x85        //時數據地址    1000 0101
  20. #define read_week_add            0x87        //星期數據地址    1000 0111
  21. #define read_month_add            0x89        //月數據地址    1000 1001
  22. #define read_day_add            0x8b        //日數據地址    1000 1011
  23. #define read_year_add            0x8d        //年數據地址    1000 1101
  24. #define read_control_add        0x8f        //控制數據地址  1000 1111
  25. #define read_charger_add        0x91         //可編程涓流充電地址  1001 0001              
  26. #define read_clkburst_add        0xbe        //時鐘脈沖串地址
  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)  //寫入數據給1302
  35. {
  36.     uchar i;
  37.     ce=0;     //禁止讀寫數據
  38.     sclk=0;   
  39.     for(i=0;i<8;i++)    //寫地址
  40.     {
  41.       ce=1;     //允許讀寫數據
  42.       sclk=0;
  43.       io=address&0x01;  
  44.       address>>=1;
  45.       sclk=1;
  46.     }
  47.     for(i=0;i<8;i++)    //寫數據
  48.     {
  49.       ce=1;    //允許讀寫數據
  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讀取時間數據
  58. {
  59.     uchar i,num;
  60.     ce=0;   //禁止讀寫數據
  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() //初始化函數 設置時間
  83. {
  84.     read_ram_data = read1302_time(read_RAM0_add);
  85.        if(rread_ram_data!=0xf0)
  86.     {
  87.         write1302_time(0x8e,0x00);  //保護取消,可以進行讀寫操作
  88.         write1302_time(write_sec_add,0x00);//寫入初始秒時間 0101 0110
  89.         write1302_time(write_min_add,0x35);//寫入初始分時間 0101 0110
  90.         write1302_time(write_hr_add,0x22); //寫入初始時時間 0101 0110
  91.         write1302_time(write_week_add,0x06); //寫入初始周時間 0101 0110
  92.         write1302_time(write_month_add,0x08); //寫入初始月時間 0101 0110
  93.         write1302_time(write_day_add,0x12); //寫入初始日時間 0101 0110
  94.         write1302_time(write_year_add,0x17); //寫入初始年時間 0101 0110
  95.         write1302_time(0x90,0xa5);    //使能涓流充電,  1010 0101
  96.         write1302_time(write_RAM0_add,0xf0); //往RAM寄存器中寫入0xf0數據,因為RAM有掉電丟失特點,所以進入初始化函數的時候首先判斷這個寄存器是否還有數據
  97.         write1302_time(0x8e,0x80);   //保護啟動,禁止對1302寫操作
  98.     }
  99. }
  100. void xianshi_data() //將從1302讀出的二進制數據轉換為十進制
  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”函數取得返回值num的數據
  104.         sec = ((read_sec&0x70)>>4)*10+(read_sec&0x0f); //十進制“秒”

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

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

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

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

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

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


主函數部分:
  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    //設置P2口工作模式   0000 0000
  9. //#define  P2M0_set  0x0d //設置P2口工作模式   0000 1110
  10. uchar num;
  11. /*************************延時函數*************************/
  12. void delay(uint a)         // 1ms延時程序(12MHz 10倍于51單片機速度時)
  13. {
  14.     uint i;
  15.     while(--a != 0)
  16.     {
  17.         for(i = 0;i < 600;i++);
  18.     }                           
  19. }
  20. /***************************************初始化IO口狀態**************************************/
  21. //void IO_init(void)
  22. //{
  23. //P2M1 = P2M1_set;
  24. //P2M0 = P2M0_set;
  25. //}
  26. /**************************************外部中斷INT2初始化函數 **************************************/
  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. }
復制代碼

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



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

使用道具 舉報

沙發
ID:82765 發表于 2017-9-2 21:31 | 只看該作者
提示: 作者被禁止或刪除 內容自動屏蔽
回復

使用道具 舉報

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

評分

參與人數 1黑幣 +30 收起 理由
admin + 30 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

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

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

使用道具 舉報

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

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

使用道具 舉報

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

使用道具 舉報

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

使用道具 舉報

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

換過了,前后都是用達拉斯的芯片
回復

使用道具 舉報

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

網上也是這么說的,我是檢測1302內部的31字節的第一位,初始化時給這一位寫入一個數據,再上電時讀取這一位是不是之前寫入的值,但是根據網上的程序修改沒有效果。
回復

使用道具 舉報

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

void init_1302() //初始化函數 設置時間
{
                write1302_time(write_control_add,0x00);  //保護取消,可以進行讀寫操作
                write1302_time(write_sec_add,0x30);//寫入初始秒時間 0101 0110
                write1302_time(write_min_add,0x05);//寫入初始分時間 0101 0110
                write1302_time(write_hr_add,0x21); //寫入初始時時間 0101 0110
                write1302_time(write_week_add,0x07); //寫入初始周時間 0101 0110
                write1302_time(write_month_add,0x09); //寫入初始月時間 0101 0110
                write1302_time(write_day_add,0x03); //寫入初始日時間 0101 0110
                write1302_time(write_year_add,0x17); //寫入初始年時間 0101 0110
                write1302_time(write_RAM0_add,0x17); //往RAM寄存器中寫入0xf0數據,因為RAM有掉電丟失特點,所以進入初始化函數的時候首先判斷這個寄存器是否還有數據
                write1302_time(write_charger_add,0xab);        //使能涓流充電,兩個二極管+8k電阻  1010 1011
                write1302_time(write_control_add,0x80);   //保護啟動,禁止對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);   //保護啟動,禁止對1302寫操作
        }
        else if((ram_data%10) != 7)
        {
                init_1302();
        }
}
回復

使用道具 舉報

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

換進口的DS1302,同樣的程序,進口的芯片可以,有些國產的芯片就是不行
回復

使用道具 舉報

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

評分

參與人數 1黑幣 +50 收起 理由
admin + 50 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

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

使用道具 舉報

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

DS1302掉電后內部RAM的值不等于3,可以判斷后初始化時間,然后標記為3即可。
回復

使用道具 舉報

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

為什么我的板是連了一個10 0000uF的電容,試了,失敗了,還是說一定要加一個3v的備用電池才能做到斷電繼續計時?
回復

使用道具 舉報

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

使用道具 舉報

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

往1302的RAM寫校驗標記是可以的 完全沒問題 我正在用 寫的是第一個地址 注意 因為1302是BCD格式寫入 如果你寫的值超過6位讀出來就只有6位 比如寫0xaa進去出來是0x2a

如果你的板子沒設計后備電池 可以在供電線路上并聯一個電池 電池的正極串聯一個二極管 和后備電池意思一樣

如果是片子斷電后再上電 也不一定非要去讀1302 寫個預處理函數 在主循環的while之前執行 只要是第一次上電 都先從1302讀時間到緩沖區 然后再到主循環里顯示 當然 這樣做的前提是1302不能斷電 否則讀出來的肯定是錯誤的時間 讀1302的RAM方法只是為了判斷是否執行調表
回復

使用道具 舉報

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

使用道具 舉報

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

使用道具 舉報

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

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

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 久久欧美高清二区三区 | 亚洲精品一区二区 | 日本午夜免费福利视频 | 国产男女视频 | 国产九九九九 | 亚洲在线 | 日韩a视频 | 最新中文字幕一区 | 免费av毛片 | 精品不卡 | 欧美成视频 | 欧美亚洲另类在线 | 久久不卡 | 特黄色一级毛片 | 久久国产精品一区二区三区 | 九九热在线视频观看这里只有精品 | 日韩在线观看视频一区 | 国产免费又色又爽又黄在线观看 | 亚洲电影成人 | 亚洲精品免费观看 | 91正在播放| 国产成人精品一区二区三区在线 | 一区二区三区四区日韩 | 小早川怜子xxxxaⅴ在线 | 一区二区三区国产 | 亚州av| 亚洲精品一区国产精品 | 精品av天堂毛片久久久借种 | 懂色中文一区二区三区在线视频 | 欧美在线视频a | 日韩av在线一区 | av香蕉 | 亚洲精品9999 | 亚洲高清av在线 | 美女天天操 | 国产午夜精品久久久 | 日韩精品一区二区三区在线观看 | 91文字幕巨乱亚洲香蕉 | 亚洲激情一区二区三区 | 亚洲欧美一区二区三区情侣bbw | 久久久精品黄色 |