標題: DS1302時鐘求助 [打印本頁]

作者: lxm41577    時間: 2022-8-8 14:49
標題: DS1302時鐘求助
       本人用AT89C51和DS1302 抄別人的軟件 制作了個時鐘,時鐘倒是可以正常走時,只是有個問題,斷電后重新通電,時間不能顯示當時時間,會回到初始化時間,時間需要重新調(diào)整,感覺是程序中少了實時時間處理這個代碼,DS1302已經(jīng)安裝了電池,本人單片機不經(jīng)常使用,自學了匯編后只會匯編,C只能看個大概,哪個高手幫幫忙看看這程序需要如何改才可以時時顯示時間,只要顯示 秒分時  時間就可以了,其他功能不需要,謝謝!

T_CLK Bit P1.6                    ;實時時鐘時鐘線引腳
T_IO  Bit P1.5                         ;實時時鐘數(shù)據(jù)線引腳
T_RST Bit P1.4                         ;實時時鐘復位線引腳

D6 BIT P2.0    ;小時十位數(shù)碼管
D5 BIT P2.1    ;小時個位數(shù)碼管
D4 BIT P2.2     ;分鐘十位數(shù)碼管
D3 BIT P2.3     ;分鐘個位數(shù)碼管
D2 BIT P2.4     ;秒十位數(shù)碼管
D1 BIT P2.5     ;秒個位數(shù)碼管


D_OUT EQU P0 ;數(shù)碼管段位連接端

DOT BIT 20H.0
POT BIT 20H.1
second     EQU     60h ;秒的緩沖區(qū)
minute     EQU     61h ;分的緩沖區(qū)
hour         EQU      62h ;小時的緩沖區(qū)
DAY         EQU      63H
MONTH   EQU      64H
WEEK       EQU      65H
YEARL      EQU       66H
;**************************************************************
;**************************************************************
ORG 00H
JMP START

ORG 0BH
JMP TIM0

ORG 30H
START: MOV SP,#70H
        MOV SECOND,#36H
MOV MINUTE,#49H
MOV HOUR,#08H
        MOV P2,#0FFH
        MOV DPTR,#TAB
lcall SETDS1302     ;DS1302初始時間
lcall GET1302          ;DS1302讀取時間
lcall  DSP               ;顯示時間子程序
MOV R1,#5FH
mov r4,#00
        mov ie,#82h
        mov tmod,#01h
        mov th0,#(65536-3000)/256
        mov tl0,#(65536-3000)mod 256
        setb tr0
;******************
DIR:  NOP
     JMP   DIR
;******************

TIM0:push acc
     push psw
     mov th0,#(65536-2000)/256
     mov tl0,#(65536-2000)mod 256
     lcall  DSP                  ;顯示時間子程序

lp2: djnz r3,lp1                 ;未到1 S繼續(xù)循環(huán)
     mov  r3,#20
     cpl dot
     CJNE R1,#5FH,LP1
     lcall GET1302                ;每過1s從DS1302讀取一次時間

lp1:pop psw
    pop acc
    reti

;****************************************************

;顯示時間掃描子程序
DSP:   CJNE R1,#60H,SS

。。。。。。。此次有代碼省略

DSP3: RET

;---------------------------------------------------------------------------------------------------
;設置DS1302初始時間,并啟動計時
SETDS1302:
        CLR     T_RST
        nop
        CLR     T_CLK
        nop
        SETB    T_RST
        nop
        MOV     B,#8EH          ;寫控制命令字
        LCALL   INPUTBYTE      
        MOV     B,#00H          ;寫保護關閉
        LCALL   INPUTBYTE
        SETB    T_CLK
        nop
        CLR     T_RST

        MOV     R0,#SECOND      ;內(nèi)存中的時間首地址
        MOV     R2,#80H         ;DS1302中的時間首地址
        MOV     R7,#7           ;字節(jié)數(shù)

SETLOOP:
        CLR     T_RST
        nop
        CLR     T_CLK
        nop
        SETB    T_RST
        nop
        MOV     B,R2            ;寫命令字
        LCALL   INPUTBYTE
        MOV     A,@R0           ;設置時間
        MOV     B,A
        LCALL   INPUTBYTE      
        INC     R0
        INC     R2
        INC     R2
        SETB    T_CLK
        nop
        CLR     T_RST
        nop
        DJNZ    R7,SETLOOP

        CLR     T_RST
        nop
        CLR     T_CLK
        nop
        SETB    T_RST
        nop
        MOV     B,#8EH
        LCALL   INPUTBYTE
        MOV     B,#80H          ;開寫保護
        LCALL   INPUTBYTE
        SETB    T_CLK
        nop
        CLR     T_RST
        nop
        RET

;---------------------------------------------------------------------------------------------------
;從DS1302讀取時間
GET1302:
        MOV     R0,#SECOND   
        MOV     R2,#81H        ;DS1302中讀時間的首地址
        MOV     R7,#7
GETLOOP:
        CLR     T_RST
        nop
        CLR     T_CLK
        nop
        SETB    T_RST
        nop
        MOV     B,R2
        LCALL   INPUTBYTE       ;寫命令字
        LCALL   OUTPUTBYTE      ;讀時間
        MOV     @R0,A           ;將從DS1302中讀取的時間從內(nèi)存中保存
        INC     R0              ;修改地址指針
        INC     R2
        INC     R2
        SETB    T_CLK
        nop
        CLR     T_RST
        nop
        DJNZ    R7,GETLOOP
        RET

;---------------------------------------------------------------------------------------------------
;向DS1302寫一個字節(jié)
INPUTBYTE:
        MOV     R4,#8
INPUTLOOP:

        MOV     A,B
        RRC     A
        MOV     B,A
        MOV     T_IO,C
        SETB    T_CLK
        NOP
        NOP
        NOP
        CLR     T_CLK
        DJNZ    R4,INPUTLOOP
        RET
;---------------------------------------------------------------------------------------------------
;從DS1302讀一個字節(jié)
OUTPUTBYTE:
        clr     a
        clr     c
        MOV     R4,#8
OUTPUTLOOP:

        NOP
        NOP
        MOV     C,T_IO
        RRC     A
        SETB    T_CLK
        NOP
        NOP
        NOP
        CLR     T_CLK
        DJNZ    R4,OUTPUTLOOP
        RET

DELAY: MOV R6,#10
  DD1: MOV R7,#248
      DJNZ R7,$
      DJNZ R6,DD1
      RET

DLAY:MOV R5,#100
     DJNZ R5,$
     RET
TAB:  DB   03H,9FH,25H,0DH,99H,49H,41H,1FH,01H,09H;0123456789
end



作者: 1qaz2wsx77    時間: 2022-8-9 08:22
匯編看不懂。但這一現(xiàn)象按C語言來說,可以看一下主程序中有個初始化DS1302的程序,看里面有沒有時間初始化,如有,去掉后再看看。
作者: mengsiu    時間: 2022-8-9 11:43
你的程序應該了每次啟動都把1302給初始化了(我沒有仔細閱讀每一句),把時鐘寄存器覆蓋了。
我的做法是在初始化程序中讀取下圖寄存器的狀態(tài),從而判斷要不要寫入初始化參數(shù)。




作者: 13205495918    時間: 2022-8-9 15:50
我記得我當時用3231的時候也是這種問題,我的解決辦法是先下載一次,然后把主程序的初始化時間注釋之后再下載一次。
作者: 神話A小王子    時間: 2022-8-9 17:27
lcall SETDS1302     ;DS1302初始時間
作者: 新昌小徐    時間: 2022-8-9 20:09
板凳說得對,RC的第0個寄存器的最高位表示是否正常計時,即時鐘停止標志,在程序的初始化步可以檢測一下這位是不是1,如果是1,就是表示掉電了,要執(zhí)行時間的初始化,把保存的默認的時間值調(diào)出來作為現(xiàn)在的時間值 ,這樣開機后你得重新設置一下才能把它改為當前時間。
如果判斷它是0,就是跳過時間的初始化,就用DS1302的時間值。
作者: mengsiu    時間: 2022-8-11 10:28
13205495918 發(fā)表于 2022-8-9 15:50
我記得我當時用3231的時候也是這種問題,我的解決辦法是先下載一次,然后把主程序的初始化時間注釋之 ...

這種方法并不是最佳解決方案。
假如以后時鐘運行不正常了或者更換電池了,就不能自動初始化了。
作者: 新鄉(xiāng)家電維修    時間: 2022-8-11 15:49
開機讀取1302的秒,判斷最高位狀態(tài),是1就初始化,是0就正常讀取1302,顯示時間。這樣就能正常工作了,
作者: lxm41577    時間: 2022-8-11 17:17
新鄉(xiāng)家電維修 發(fā)表于 2022-8-11 15:49
開機讀取1302的秒,判斷最高位狀態(tài),是1就初始化,是0就正常讀取1302,顯示時間。這樣就能正常工作了,

能給例程嗎?DS1302我不熟,非常感謝
作者: wdmcp    時間: 2022-8-11 18:19
我現(xiàn)在也是這個問題,沒好意思發(fā)上來,拖延了很久,打開keil,然后玩手機,然后關電腦。。
作者: noble64    時間: 2022-8-12 15:47
主程序的初始化時間注釋之后再下載一次。

作者: 188610329    時間: 2022-8-12 23:04
lxm41577 發(fā)表于 2022-8-11 17:17
能給例程嗎?DS1302我不熟,非常感謝

要抄也抄好點的呀,這還不如C寫的呢……

把你這段程序:
START: MOV SP,#70H
        MOV SECOND,#36H
MOV MINUTE,#49H
MOV HOUR,#08H
        MOV P2,#0FFH
        MOV DPTR,#TAB
lcall SETDS1302     ;DS1302初始時間
lcall GET1302          ;DS1302讀取時間
修改成下面的:

START: MOV SP,#70H
MOV P2,#0FFH
MOV DPTR,#TAB

lcall GET1302          ;DS1302讀取時間


MOV A,SECOND
JNB ACC.7,NOT_SET_Time
MOV SECOND,#36H
MOV MINUTE,#49H
MOV HOUR,#08H
lcall SETDS1302     ;DS1302初始時間
NOT_SET_Time:
lcall GET1302          ;DS1302讀取時間




作者: lxm41577    時間: 2022-8-14 08:17
188610329 發(fā)表于 2022-8-12 23:04
要抄也抄好點的呀,這還不如C寫的呢……

把你這段程序:

非常感謝您的幫忙,程序運行成功,不怕你笑話,我開始學的是匯編,C沒怎么學,所以C非常不熟悉,只能看個大概,匯編都是湊合用編程只是愛好,再次感謝
作者: huangjingjie    時間: 2022-8-19 22:31
我也是網(wǎng)上抄別人的方法,斷電后時間仍在繼續(xù)走時。方法是單片機燒寫兩次,第一次把初始化時間設置好編譯后寫進單片機,二次把初始化時間注釋掉再次編譯燒寫進單片機。樓主可以試一下。方法在stc89c52上試過多遍時間主電源斷電后走時正常
作者: lxm41577    時間: 2022-8-20 14:12
huangjingjie 發(fā)表于 2022-8-19 22:31
我也是網(wǎng)上抄別人的方法,斷電后時間仍在繼續(xù)走時。方法是單片機燒寫兩次,第一次把初始化時間設置好編譯后 ...

這個方法我先前就試過,沒有成功,不過謝謝你
作者: man1234567    時間: 2022-8-24 15:35
總結一下上面的回答,供參考:
1、問題出在每次啟動都先  lcall SETDS1302     ;DS1302初始時間
   解決方法:一是如14樓說的寫二次;二是如一眾所說直接刪除這句(可取下電池看好不好用);
                  三是給他句加個觸發(fā)條件,在需要調(diào)整時間時可以調(diào)整時間才有時鐘的樣子
2、感覺在壇子里;斓亩嗍菬嵝牡耐婕遥捕嗖皇强瓢喑錾,至少俺是所以僅供參考
3、匯編和C各有千秋,只是C代碼如白話文但執(zhí)行效率那個了點但有更多例程可以找更多樂子
作者: cclianbao    時間: 2023-3-16 14:20
DS1372供電端加一個47uf以上的電解電容,這樣通電的時候就時間就不會重置了。原來我也遇到這樣的問題,就是這樣解決的。
作者: 1860774xxxx    時間: 2023-3-17 12:27
滿足條件實行初始化 不滿足則跳過

Screenshot_20230317_122449_edit_1177395346551561.jpg (191.67 KB, 下載次數(shù): 107)

Screenshot_20230317_122449_edit_1177395346551561.jpg

作者: 新鄉(xiāng)家電維修    時間: 2023-3-18 09:21
我給你個完美的解決方法吧,這是我的程序給你截取一段:

        LCALL GET1302      ;開機讀出DS1302的時間
        MOV A,SECOND     ;讀出的秒寄存器放入A
        ANL A,#80H               ;只保留秒寄存器最高位,判斷最高位狀態(tài)
        JZ MAIN                      ;A為0就轉移到主程序,否則就執(zhí)行初始化DS1302程序
        LCALL CSHDS1302        ;執(zhí)行初始化DS1302程序
;-----------------主程序-------------------------
MIAN:
.......



簡單高效,






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