功能:使用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闹钟报警的中断输入端口。
BT_DSP BIT 00H;控制显示时间或闹钟的标志位
BT_ALM BIT 01H;控制闹钟是否响铃的标志位
BT_TM2 BIT 02H;控制显示时间的模式,1:只显示时分,0:还显示年月日,星期
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
用户1400119 2007-10-12 19:59
eleclike 2007-10-7 19:10
非常抱歉,可能是在编辑这篇日志的时候弄错了,在 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
用户23382 2007-9-30 16:47
LJMP ERR_KEY
YR_KEY: CJNE A,#03H,ERR_KEY
CJNE R4,#1,MTH_KEY
为何仿真通不过?好像程序有问题。请给一个正确的答案。对你的程序我很有兴趣,能否把你的电话留给我,我们联系一下。谢谢。
用户15079 2007-9-22 08:04
用户138848 2007-9-12 16:38
eleclike 2007-9-4 20:38