日志档案

发表于 2007-8-18 15:41:30

0

标签: DS12887  时钟  闹钟  

用DS12887时钟芯片制作的时钟闹钟系统

功能:使用DS12887作为时钟的发生和保持电路,DS12887内部集成晶振和电池,断电情况下可运行10年左右;同时其内部有128字节非易失性RAM,可以保持时钟和闹钟信息;主控电路为AT89S52,p1口用作4位一体数码管的动态显示,p0,p2口作为读写DS12887总线,同时使用了/WR和/RD,p3.0的LED来实现每秒的闪烁,p3.1控制闹钟显示LED,p2口虽用作地址总线,但只使用了p2.7连接至DS12887的/CS端,所以使用了p2.0作为蜂鸣器的控制口;p3.3(/INT1)作为DS12887闹钟报警的中断输入端口。
 

显示模式有:1,仅显示闹钟;2,仅显示分秒;3,一分钟之内先显示年份(只显示后两位),与星期同时显示,再显示月日,其余时间显示时分.
调节按钮:P3.0,P3.1,P3.4,P3.5分别接4个按钮开关,分别定义为"A","T","H","M";按下"A","H"/"M",可分别调节闹钟的时分;按下"T","H"/"M",可分别调节时间的时分;时间的其他信息在该版本中不可以调节。
 
完整工程包:rar
 
;以下为源程序(仅供参考,可能编辑有误,正确程序请参考工程包):
RG_DLY  EQU  2H;延时使用的工作寄存器
    
RG_KEY EQU 30H;存储键盘值
RG_KN EQU 33H;存储调节年月日星期的次数按钮。
RG_BT1  EQU  31H;需要显示的数据暂存RAM
RG_BT2  EQU  32H

BT_DSP BIT 00H;控制显示时间或闹钟的标志位
BT_ALM BIT 01H;控制闹钟是否响铃的标志位
BT_TM2  BIT 02H;控制显示时间的模式,1:只显示时分,0:还显示年月日,星期

BT_MNSC BIT 03H;控制显示时间的分秒 
RG_TSC EQU 40H;时钟和闹钟暂存RAM,顺序同DS12C887中的RAM
RG_ASC EQU 41H
RG_TMN EQU 42H;
RG_AMN EQU 43H;
RG_THR EQU 44H
RG_AHR EQU 45H
RG_WK EQU 46H
RG_DAY EQU 47H
RG_MTH EQU 48H
RG_YR EQU 49H
 
RG_MS EQU 51H
RG_IDL EQU 50H


 ORG  0000H
 LJMP MAIN

 ORG 0013H
 LJMP SB_ALM
 ORG  0030H

MAIN: MOV  SP,#60H  
 SETB BT_DSP
 CLR BT_ALM
 CLR BT_TM2
 CLR BT_MNSC
 CLR IT1  
      SETB  EX1     
      SETB IT0 
 SETB EX0

 SETB  EA ;开总中断

 MOV  DPTR,#000BH;闹钟中断允许
 MOV A,#22H  
 MOVX  @DPTR,A
 ;====--------------------最初写入DS12887的时候使用这一条指令。
 ;LCALL SB_INI;最初的初始化时使用的。  
 ;====--------------------
 MOV  DPTR,#000AH;判断是否需要初始化 
 MOVX  A,@DPTR  
 ANL  A,#01110000B       
 CJNE  A,#20H,INI_MAI
 LJMP LP1_MAI 
INI_MAI:LCALL SB_INI

 

;------------------------------------------------------------------
;主程序循环段--开始
;------------------------------------------------------------------
LP1_MAI:LCALL SB_RD
 LCALL SB_KEY

LP3_MAI:JNB BT_ALM,DSP_MAI ;判断控制位决定是否闹铃
 CLR  P3.1
 CLR P2.0
 


DSP_MAI:
 JNB BT_MNSC,DSP2_MAI
 MOV RG_BT2,RG_TMN
 MOV RG_BT1,RG_TSC
 LCALL SB_DSP
 LJMP RT_MAI
DSP2_MAI:
 JB BT_DSP,TM_MAI;BT_DSP为1,则跳至显示时间段
AL_MAI: MOV RG_BT2,RG_AHR;;BT_DSP为0,则显示闹钟
 MOV RG_BT1,RG_AMN
 LCALL SB_DSP
 LJMP RT_MAI
 
TM_MAI: ;根据RG_SC的十位来决定时间显示的内容,
 MOV A,RG_TSC
 ANL A,#0F0H
 SWAP A; 取得秒的十位
 JNZ TM3_MAI;每分钟的开始后,用来控制仅显示时分。
 CLR BT_TM2
TM3_MAI:JB BT_TM2,TM2_MAI

;=======
;显示年月日星期 
YR_MAI: CJNE A,#2,DAY_MAI
 MOV RG_BT2,RG_YR
 MOV RG_BT1,RG_WK
 ORL RG_BT1,#0F0H
 LCALL SB_DSP
 LJMP RT_MAI
DAY_MAI:CJNE A,#4,TM2_MAI
 MOV RG_BT2,RG_MTH
 MOV RG_BT1,RG_DAY

 MOV A,RG_MTH
 ANL A,#0F0H
 SWAP A
 JNZ DAY1_MAI
 ORL RG_BT2,#0F0H
DAY1_MAI:
 MOV A,RG_DAY
 ANL A,#0F0H
 SWAP A
 JNZ DAY2_MAI 
 ORL RG_BT1,#0F0H
DAY2_MAI:
 LCALL SB_DSP
 LJMP RT_MAI
;显示时分
TM2_MAI:
 MOV A,RG_TSC
 MOV C,ACC.0
 JC XIMIE
 CLR P3.0
 LJMP DIANL
XIMIE: SETB P3.0

DIANL: NOP
 MOV RG_BT2,RG_THR
 MOV RG_BT1,RG_TMN
 LCALL SB_DSP 

;=====-= 
RT_MAI: LJMP LP1_MAI
;-------------------------------------------------------------------------
;主程序循环段--结束
;-------------------------------------------------------------------------

 

;=======按键处理子程序
SB_KEY: SETB P3.0
 SETB P3.1
 SETB P3.4 
 SETB P3.5
 MOV A,P3
 ANL A,#33H
 CJNE A,#33H,DL_KEY
 LJMP RT_KEY
 
DL_KEY: LCALL SB_DSP;去抖延时
 LCALL SB_DSP
 LCALL SB_DSP
 LCALL SB_DSP
 LCALL SB_DSP
 CJNE A,#33H,KP_KEY
 LJMP RT_KEY

KP_KEY: MOV RG_KEY,A;保留键值
 
  CLR BT_ALM;任何按键,使闹钟停止
 SETB P2.0
 SETB BT_TM2;任何按键,使得一分钟内只显示时分,不显示YEAR,DAY,WEEK
;----仅显示分秒的控制段--------
MNSC_KEY:
 CJNE A,#23H,TM_KEY
 CPL BT_MNSC
 LJMP RT_KEY
;-----------------------------------

TM_KEY: CJNE A,#32H,AL_KEY
 MOV RG_BT2,RG_THR
 MOV RG_BT1,RG_TMN
 LCALL SB_DSP
 SETB BT_DSP;设置该位,在主程序中判断该位为1,则显示时间
 LJMP RT_KEY

AL_KEY: CJNE A,#31H,THR_KEY
 MOV RG_BT2,RG_AHR
 MOV RG_BT1,RG_AMN
 LCALL SB_DSP
 CLR BT_DSP;设置该位,在主程序中判断该位为0,则显示闹钟
 LJMP RT_KEY

THR_KEY:CJNE A,#12H,TMN_KEY; 校正时钟的时
 MOV A,RG_THR
 ADD A,#1
 DA A
 CJNE A,#24H,LP1_KEY
 CLR A
LP1_KEY:MOV RG_THR,A
 MOV RG_BT2,RG_THR;显示校正的时间
 MOV RG_BT1,RG_TMN
 LCALL SB_DSP
 MOV DPTR,#0004H
 MOVX @DPTR,A
 LJMP SB_KEY

TMN_KEY:CJNE A,#22H,AHR_KEY
 MOV A,RG_TMN 
 ADD A,#1
 DA A
 CJNE A,#60H,LP2_KEY
 CLR A
LP2_KEY:MOV RG_TMN,A
 MOV RG_BT2,RG_THR
 MOV RG_BT1,RG_TMN
 LCALL SB_DSP
 MOV DPTR,#0002H
 MOVX @DPTR,A
 LJMP SB_KEY

AHR_KEY:CJNE A,#11H,AMN_KEY
 MOV A,RG_AHR 
 ADD A,#1
 DA A
 CJNE A,#24H,LP3_KEY
 CLR A
LP3_KEY:MOV RG_AHR,A
 MOV RG_BT2,RG_AHR
 MOV RG_BT1,RG_AMN
 LCALL SB_DSP
 MOV DPTR,#0005H
 MOVX @DPTR,A
 LJMP SB_KEY

AMN_KEY:CJNE A,#21H,OTH_KEY
 MOV A,RG_AMN 
 ADD A,#1
 DA A
 CJNE A,#60H,LP4_KEY
 CLR A
LP4_KEY:MOV RG_AMN,A
 MOV RG_BT2,RG_AHR
 MOV RG_BT1,RG_AMN
 LCALL SB_DSP 
 MOV DPTR,#0003H
 MOVX @DPTR,A
 LJMP SB_KEY

OTH_KEY:CJNE A,#30H,YR_KEY
 INC R4
 CJNE R4,#6,YR_KEY
 MOV R4,#0
 LJMP ERR_KEY

YR_KEY: CJNE A,#03H,ERR_KEY
 CJNE R4,#1,MTH_KEY
 MOV RG_BT2,#0FFH
 MOV RG_BT1,RG_YR
 LCALL SB_DSP
 MOV A,RG_YR
 ADD A,#1
 DA A
 MOV DPTR,#0009H
 MOVX @DPTR,A
 LCALL SB_DSP

RT_KEY: RET

;======闹钟子程序,中断处理程序
SB_ALM: PUSH  ACC
 MOV DPTR,#000CH
 MOVX  A,@DPTR 
 SETB BT_ALM
 POP ACC
 RETI

;======初始化DS12C887子程序
SB_INI:PUSH ACC
 MOV  DPTR,#000BH  
 MOV  A,#82H
 MOVX  @DPTR,A  
;----初始化时钟,23:59:50,初始化闹钟:00:00:00
 MOV  DPTR,#0000H 
 MOV A,#50H
 MOVX  @DPTR,A
 INC  DPTR  
 MOV A,#00H
 MOVX  @DPTR,A
 INC  DPTR 
 MOV A,#59H
 MOVX  @DPTR,A
 INC  DPTR  
 MOV A,#00H
 MOVX  @DPTR,A
 INC  DPTR  
 MOV A,#23H
  MOVX  @DPTR,A
 INC  DPTR  
 MOV A,#00H
 MOVX  @DPTR,A
;---初始化星期7(日), 年,月,日2007-7-29
 INC  DPTR     
 MOV  A,#07H
 MOVX  @DPTR,A  
 INC  DPTR   
 MOV  A,#29H
 MOVX  @DPTR,A 
 INC  DPTR   
 MOV  A,#07H
 MOVX  @DPTR,A 
 INC  DPTR 
 MOV  A,#07H
 MOVX  @DPTR,A    
 MOV DPTR,#0032H
 MOV A,#20H
 MOVX @DPTR,A 

 NOP
 MOV  DPTR,#000AH 
 MOV  A,#20H
 MOVX  @DPTR,A  
 INC  DPTR  
 MOV  A,#22H
 MOVX  @DPTR,A 
 INC  DPTR 
 MOVX  A,@DPTR 

 POP ACC
 RET


;======读DS12887子程序------

SB_RD: PUSH ACC
;---读时分秒的时钟,
 MOV DPTR,#0000H;闹钟的秒
 MOVX A,@DPTR
 MOV RG_TSC,A
 INC DPTR;时钟的秒
 MOVX A,@DPTR
 MOV RG_ASC,A
 INC DPTR;闹钟的分
 MOVX A,@DPTR
 MOV RG_TMN,A
 INC DPTR;时钟的分
 MOVX A,@DPTR
 MOV RG_AMN,A
 INC DPTR;闹钟的时
 MOVX A,@DPTR
 MOV RG_THR,A
 INC DPTR;时钟的时
 MOVX A,@DPTR
 MOV RG_AHR,A
 
;---读年月日,星期
 MOV DPTR,#0006H;读星期
 MOVX A,@DPTR
 MOV RG_WK,A
 INC DPTR;读日 
 MOVX A,@DPTR
 MOV RG_DAY,A
 INC DPTR;读月
 MOVX A,@DPTR
 MOV RG_MTH,A
 INC DPTR;读年
 MOVX A,@DPTR
 MOV RG_YR,A
 
 POP ACC 
  RETI
 
;======显示子程序
SB_DSP: PUSH ACC
 MOV R1,#RG_BT2
 MOV  R6,#10H ;R6寄存器选择位
 MOV R7,#2
 
LP1_DSP:MOV A,@R1
 ANL A,#0F0H
 SWAP A
 ORL A,R6
 MOV  P1,A ;送到P1口
 MOV  RG_DLY,#10 ;调延时子程序
 LCALL SB_DLY
 MOV A,R6
 RL A
 MOV R6,A
  
 MOV A,@R1
 ANL A,#0FH
 ORL A,R6
 MOV  P1,A ;送到P1口
 MOV  RG_DLY,#10 ;调延时子程序
 LCALL SB_DLY
 MOV A,R6
 RL A
 MOV R6,A

 DEC R1
 DJNZ R7,LP1_DSP

RT_DSP: POP ACC
 RET

;=======延时子程序
SB_DLY: PUSH    RG_DLY  ;
LP1_DLY:PUSH    RG_DLY
LP2_DLY:PUSH    RG_DLY
 DJNZ R2,$
        POP     RG_DLY
        DJNZ    R2,LP2_DLY
        POP     RG_DLY
        DJNZ    R2,LP1_DLY
 POP     RG_DLY
        DJNZ    R2,SB_DLY
 RET

 END

系统分类: 单片机   |   用户分类: el制作   |   来源: 原创   |   【推荐给朋友】

    阅读(1720)    回复(7)  

投一票您将和博主都有获奖机会!

  • zhfq

    2007-9-4 19:05:50

    还用这么老的东西啊

  • eleclike

    2007-9-4 20:38:12

    手头上有一快12887,舍不得扔了,就做一个玩玩,可以当作年历用用.

  • xuexi

    2007-9-12 16:38:05

    我也有一块,改天也来玩下呵呵

  • XIONG

    2007-9-22 8:04:39

    我也有一块,改天也来玩下呵呵

  • 爱好者

    2007-9-30 16:47:46


     LJMP ERR_KEY

    YR_KEY: CJNE A,#03H,ERR_KEY
     CJNE R4,#1,MTH_KEY

    为何仿真通不过?好像程序有问题。请给一个正确的答案。对你的程序我很有兴趣,能否把你的电话留给我,我们联系一下。谢谢。

  • eleclike

    2007-10-7 19:10:29

    非常抱歉,可能是在编辑这篇日志的时候弄错了,在   RT_KEY: RET的前面有一个标号删除了:  “ERR_KEY:”,

    我的邮箱是eleclike@qq.com,有什么问题可以通过邮件交流,也可以给我留言。

     

    改正后的部分程序如下

    LJMP ERR_KEY

    YR_KEY: CJNE A,#03H,ERR_KEY
     CJNE R4,#1,MTH_KEY
     MOV RG_BT2,#0FFH
     MOV RG_BT1,RG_YR
     LCALL SB_DSP
     MOV A,RG_YR
     ADD A,#1
     DA A
     MOV DPTR,#0009H
     MOVX @DPTR,A
     LCALL SB_DSP

        ERR_KEY:; +++++增加的语句+++++

    RT_KEY: RET

  • YUQIU

    2007-10-12 19:59:15

    有没有C语言版本的程序/