找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2901|回复: 19
收起左侧

DS1302时钟求助

  [复制链接]
ID:76044 发表于 2022-8-8 14:49 | 显示全部楼层 |阅读模式
       本人用AT89C51和DS1302 抄别人的软件 制作了个时钟,时钟倒是可以正常走时,只是有个问题,断电后重新通电,时间不能显示当时时间,会回到初始化时间,时间需要重新调整,感觉是程序中少了实时时间处理这个代码,DS1302已经安装了电池,本人单片机不经常使用,自学了汇编后只会汇编,C只能看个大概,哪个高手帮帮忙看看这程序需要如何改才可以时时显示时间,只要显示 秒分时  时间就可以了,其他功能不需要,谢谢!

T_CLK Bit P1.6                    ;实时时钟时钟线引脚
T_IO  Bit P1.5                         ;实时时钟数据线引脚
T_RST Bit P1.4                         ;实时时钟复位线引脚

D6 BIT P2.0    ;小时十位数码管
D5 BIT P2.1    ;小时个位数码管
D4 BIT P2.2     ;分钟十位数码管
D3 BIT P2.3     ;分钟个位数码管
D2 BIT P2.4     ;秒十位数码管
D1 BIT P2.5     ;秒个位数码管


D_OUT EQU P0 ;数码管段位连接端

DOT BIT 20H.0
POT BIT 20H.1
second     EQU     60h ;秒的缓冲区
minute     EQU     61h ;分的缓冲区
hour         EQU      62h ;小时的缓冲区
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继续循环
     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      ;内存中的时间首地址
        MOV     R2,#80H         ;DS1302中的时间首地址
        MOV     R7,#7           ;字节数

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中读取的时间从内存中保存
        INC     R0              ;修改地址指针
        INC     R2
        INC     R2
        SETB    T_CLK
        nop
        CLR     T_RST
        nop
        DJNZ    R7,GETLOOP
        RET

;---------------------------------------------------------------------------------------------------
;向DS1302写一个字节
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读一个字节
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


回复

使用道具 举报

ID:86421 发表于 2022-8-9 08:22 | 显示全部楼层
汇编看不懂。但这一现象按C语言来说,可以看一下主程序中有个初始化DS1302的程序,看里面有没有时间初始化,如有,去掉后再看看。
回复

使用道具 举报

ID:16255 发表于 2022-8-9 11:43 | 显示全部楼层
你的程序应该了每次启动都把1302给初始化了(我没有仔细阅读每一句),把时钟寄存器覆盖了。
我的做法是在初始化程序中读取下图寄存器的状态,从而判断要不要写入初始化参数。
未命名.jpg
未命名2.jpg

回复

使用道具 举报

ID:908826 发表于 2022-8-9 15:50 | 显示全部楼层
我记得我当时用3231的时候也是这种问题,我的解决办法是先下载一次,然后把主程序的初始化时间注释之后再下载一次。
回复

使用道具 举报

ID:386442 发表于 2022-8-9 17:27 | 显示全部楼层
lcall SETDS1302     ;DS1302初始时间
回复

使用道具 举报

ID:496636 发表于 2022-8-9 20:09 | 显示全部楼层
板凳说得对,RC的第0个寄存器的最高位表示是否正常计时,即时钟停止标志,在程序的初始化步可以检测一下这位是不是1,如果是1,就是表示掉电了,要执行时间的初始化,把保存的默认的时间值调出来作为现在的时间值 ,这样开机后你得重新设置一下才能把它改为当前时间。
如果判断它是0,就是跳过时间的初始化,就用DS1302的时间值。
回复

使用道具 举报

ID:16255 发表于 2022-8-11 10:28 | 显示全部楼层
13205495918 发表于 2022-8-9 15:50
我记得我当时用3231的时候也是这种问题,我的解决办法是先下载一次,然后把主程序的初始化时间注释之 ...

这种方法并不是最佳解决方案。
假如以后时钟运行不正常了或者更换电池了,就不能自动初始化了。
回复

使用道具 举报

ID:72088 发表于 2022-8-11 15:49 | 显示全部楼层
开机读取1302的秒,判断最高位状态,是1就初始化,是0就正常读取1302,显示时间。这样就能正常工作了,
回复

使用道具 举报

ID:76044 发表于 2022-8-11 17:17 | 显示全部楼层
新乡家电维修 发表于 2022-8-11 15:49
开机读取1302的秒,判断最高位状态,是1就初始化,是0就正常读取1302,显示时间。这样就能正常工作了,

能给例程吗?DS1302我不熟,非常感谢
回复

使用道具 举报

ID:725922 发表于 2022-8-11 18:19 | 显示全部楼层
我现在也是这个问题,没好意思发上来,拖延了很久,打开keil,然后玩手机,然后关电脑。。
回复

使用道具 举报

ID:603753 发表于 2022-8-12 15:47 | 显示全部楼层
主程序的初始化时间注释之后再下载一次。
回复

使用道具 举报

ID:624769 发表于 2022-8-12 23:04 | 显示全部楼层
lxm41577 发表于 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读取时间



回复

使用道具 举报

ID:76044 发表于 2022-8-14 08:17 | 显示全部楼层
188610329 发表于 2022-8-12 23:04
要抄也抄好点的呀,这还不如C写的呢……

把你这段程序:

非常感谢您的帮忙,程序运行成功,不怕你笑话,我开始学的是汇编,C没怎么学,所以C非常不熟悉,只能看个大概,汇编都是凑合用编程只是爱好,再次感谢
回复

使用道具 举报

ID:229502 发表于 2022-8-19 22:31 | 显示全部楼层
我也是网上抄别人的方法,断电后时间仍在继续走时。方法是单片机烧写两次,第一次把初始化时间设置好编译后写进单片机,二次把初始化时间注释掉再次编译烧写进单片机。楼主可以试一下。方法在stc89c52上试过多遍时间主电源断电后走时正常
回复

使用道具 举报

ID:76044 发表于 2022-8-20 14:12 | 显示全部楼层
huangjingjie 发表于 2022-8-19 22:31
我也是网上抄别人的方法,断电后时间仍在继续走时。方法是单片机烧写两次,第一次把初始化时间设置好编译后 ...

这个方法我先前就试过,没有成功,不过谢谢你
回复

使用道具 举报

ID:584814 发表于 2022-8-24 15:35 | 显示全部楼层
总结一下上面的回答,供参考:
1、问题出在每次启动都先  lcall SETDS1302     ;DS1302初始时间
   解决方法:一是如14楼说的写二次;二是如一众所说直接删除这句(可取下电池看好不好用);
                  三是给他句加个触发条件,在需要调整时间时可以调整时间才有时钟的样子
2、感觉在坛子里常混的多是热心的玩家,也多不是科班出生的,至少俺是所以仅供参考
3、汇编和C各有千秋,只是C代码如白话文但执行效率那个了点但有更多例程可以找更多乐子
回复

使用道具 举报

ID:683123 发表于 2023-3-16 14:20 | 显示全部楼层
DS1372供电端加一个47uf以上的电解电容,这样通电的时候就时间就不会重置了。原来我也遇到这样的问题,就是这样解决的。
回复

使用道具 举报

ID:468209 发表于 2023-3-17 12:27 来自手机 | 显示全部楼层
满足条件实行初始化 不满足则跳过
Screenshot_20230317_122449_edit_1177395346551561.jpg
回复

使用道具 举报

ID:72088 发表于 2023-3-18 09:21 | 显示全部楼层
我给你个完美的解决方法吧,这是我的程序给你截取一段:

        LCALL GET1302      ;开机读出DS1302的时间
        MOV A,SECOND     ;读出的秒寄存器放入A
        ANL A,#80H               ;只保留秒寄存器最高位,判断最高位状态
        JZ MAIN                      ;A为0就转移到主程序,否则就执行初始化DS1302程序
        LCALL CSHDS1302        ;执行初始化DS1302程序
;-----------------主程序-------------------------
MIAN:
.......



简单高效,

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表