欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

標題: DS1302掉電不丟失時間單片機程序編寫問題 [打印本頁]

作者: jianwei2030    時間: 2017-9-2 20:51
標題: 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




作者: cjjcjj1    時間: 2017-9-2 21:31
提示: 作者被禁止或刪除 內容自動屏蔽
作者: 黑暗人才    時間: 2017-9-2 23:08
你可以修改一下你的初始化函數,DS1302里面不是有好多空著的寄存器嘛,你可以先檢測某一個寄存器是否為0,為零就初始化,初始化完畢后給這個寄存器寫1,這樣就可以了
作者: jianwei2030    時間: 2017-9-3 20:09
黑暗人才 發表于 2017-9-2 23:08
你可以修改一下你的初始化函數,DS1302里面不是有好多空著的寄存器嘛,你可以先檢測某一個寄存器是否為0, ...

網上的說法也是這樣做,初始化時在1302的ram中寫入一個數值,以后每次上電都檢測這個數值,如果檢測到就不執行初始化程序,檢測不到就執行初始化程序。但是我想知道怎么寫這個檢測程序。
作者: jianwei2030    時間: 2017-9-3 20:14
cjjcjj1 發表于 2017-9-2 21:31
你好!
1、要想斷電時鐘繼續走時,1302要加后備電池
2、斷電后,重啟,時鐘恢復 17年8月12日

后備電池是有加3V紐扣電池的;刪掉初始化函數后第一次上電就什么也不顯示了,我希望第一次上電時顯示一個初始時間,用戶在這個時間的基礎上再修改。
作者: 越快樂越墮落    時間: 2017-9-4 22:49
屏蔽掉初始化
作者: mengx    時間: 2017-9-5 10:48
電路沒問題,不同公司的1302驅動方法上可能存在不同,我也遇到過同樣的問題,換個1302就好了
作者: jianwei2030    時間: 2017-9-7 21:53
mengx 發表于 2017-9-5 10:48
電路沒問題,不同公司的1302驅動方法上可能存在不同,我也遇到過同樣的問題,換個1302就好了

換過了,前后都是用達拉斯的芯片
作者: jianwei2030    時間: 2017-9-7 21:56
黑暗人才 發表于 2017-9-2 23:08
你可以修改一下你的初始化函數,DS1302里面不是有好多空著的寄存器嘛,你可以先檢測某一個寄存器是否為0, ...

網上也是這么說的,我是檢測1302內部的31字節的第一位,初始化時給這一位寫入一個數據,再上電時讀取這一位是不是之前寫入的值,但是根據網上的程序修改沒有效果。
作者: jianwei2030    時間: 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();
        }
}

作者: lids    時間: 2017-10-10 15:58
jianwei2030 發表于 2017-9-7 21:53
換過了,前后都是用達拉斯的芯片

換進口的DS1302,同樣的程序,進口的芯片可以,有些國產的芯片就是不行
作者: kingyork    時間: 2018-7-2 01:29
DS1302掉電后內部RAM的值不等于3,可以判斷后初始化時間,然后標記為3即可。
作者: 家哈哈哈哈    時間: 2018-7-2 09:40
你們也太厲害了吧
作者: 家哈哈哈哈    時間: 2018-7-2 09:41

DS1302掉電后內部RAM的值不等于3,可以判斷后初始化時間,然后標記為3即可。
作者: Misol    時間: 2019-3-26 20:44
我還看到過說1302的vcc2連接一個10000uF的電容,就可以斷電也能繼續計時,說再加一個write1302_time(0x90,0xa6);就可以
這個說法是真的嗎?

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

作者: 白幽幽    時間: 2020-3-30 18:50
我以上方法都試了都不行
作者: dzbj    時間: 2020-3-30 20:48
不明白你說的不成都什么不成 也沒太看明白你要求什么 1302這東西 掉電就沒時間了 必須要重新寫入時間

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

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

如果是片子斷電后再上電 也不一定非要去讀1302 寫個預處理函數 在主循環的while之前執行 只要是第一次上電 都先從1302讀時間到緩沖區 然后再到主循環里顯示 當然 這樣做的前提是1302不能斷電 否則讀出來的肯定是錯誤的時間 讀1302的RAM方法只是為了判斷是否執行調表
作者: mkkop    時間: 2020-3-30 21:30
軟件你已經寫好了,而且是可以正常使用的,現在最簡單的方法就是用一個IO口來判斷是否需要初始化即可,
例如你的P55腳是空的,在初始化前面先判斷P55,是0的話初始化,是1就不初始化,你燒錄好程序,如果想要初始化就把P55接地再上電就會初始化了,不需要初始化時懸空即可,多簡單啊
作者: 余生不負    時間: 2020-3-30 23:51
這個問題啊,時間初始化是程序的問題,要設置一下那個什么命令,不太記得了,我DS1302,都是直接調用程序,改一下IO口就可以用了,你找的程序不對,你這個是程序初始化的時候把時間給初始化了。
作者: 白幽幽    時間: 2020-3-31 09:11
黑暗人才 發表于 2017-9-2 23:08
你可以修改一下你的初始化函數,DS1302里面不是有好多空著的寄存器嘛,你可以先檢測某一個寄存器是否為0, ...

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




歡迎光臨 (http://m.raoushi.com/bbs/) Powered by Discuz! X3.1