电路图:
汇编代码:
ORG 0000H
LJMP MAIN
ORG 000BH
LJMP TIME
ORG 0100H
;宏定义
;键位
K0 BIT 20H.0
K1 BIT 20H.1
K2 BIT 20H.2
K3 BIT 20H.3
K4 BIT 20H.4
;暂存区
ST DATA 68H
MT DATA 69H
HT DATA 6AH
DT DATA 6BH
MOUT DATA 6CH
YLT DATA 6DH
YHT DATA 6EH
SPT DATA 21H ;移位指针
;时钟时间寄存区
S DATA 60H
M DATA 61H
H DATA 62H
D DATA 63H
MOU DATA 64H
YL DATA 65H
YH DATA 66H
FLAG DATA 67H
;闹钟时间寄存区
SC DATA 50H
MC DATA 51H
HC DATA 52H
DC DATA 53H
MOUC DATA 54H
YLC DATA 55H
YHC DATA 56H
;时间显示缓冲区
//存放数码管显示16位的数据
SDL DATA 70H
SDH DATA 71H
POINT1 DATA 72H
MDL DATA 73H
MDH DATA 74H
POINT2 DATA 75H
HDL DATA 76H
HDH DATA 77H
DDL DATA 78H
DDH DATA 79H
MOUDL DATA 7AH
MOUDH DATA 7BH
YD0 DATA 7CH
YD1 DATA 7DH
YD2 DATA 7EH
YD3 DATA 7FH
//主程序
MAIN:
MOV TMOD,#01H ;T0工作方式1
MOV TL0,#0B0H
MOV TH0,#3CH ;50ms
MOV R7,#20 ;20*50ms = 1s
MOV S,#50
MOV M,#59
MOV H,#11
MOV D,#11
MOV MOU,#12
MOV YL,#20
MOV YH,#20
MOV POINT1,#10 ;在TABLE中第10个对应“-”
MOV POINT2,#10
MOV SPT,#1 ;移位指针初始最低位为1
SETB K0
CLR K1 ;K1置1 (非暂停状态)
CLR K2 ;K2置1 默认修改模式
CLR P3.5 ;默认蜂鸣器非工作状态
CLR P3.6 ;默认LED非工作状态
SETB ET0
SETB EA
SETB TR0 ;开启定时器
;不断循环
GO_ON:
LCALL CHECK_KEY
LCALL DISPLAY
LCALL CHECK_CLOCK ;闹铃
LCALL LIGHT_ON ;开灯
LCALL LIGHT_OFF ;关灯
SJMP GO_ON ;跳转循环
;定时子程序
TIME:
MOV TL0,#0B0H
MOV TH0,#3CH
DJNZ R7,TIME_END
MOV R7,#20 ;循环20次 定时1s
LCALL TIME_INC ;跳转到计时
LCALL SAVE0 ;跳转到数据转移
LCALL SEND_TO_DIS ;储存时间寄存器中的BCD
TIME_END:
RETI
;数码管显示子程序
DISPLAY:
MOV R0,#SDL ;数据缓存区指针
MOV DPTR,#TABLE ;七段共阴数码管0-9显示
MOV R1,#0 ;R1存放表示第几位的数字
//P0口实现片选
NEXT: MOV P0,R1 ;显示位连接P0
MOV A,R1
CLR C
SUBB A,#8 //实现前8个向HMS跳转,后8个向YMD跳转
JC HMS
//P2口实现年月日
DIAN1: //先判断是否位第10位,第10位需要有小数点
CJNE R1,#10,DIAN2 ;跳转判断DIAN2
MOV DPTR,#TABLE1
MOV A,@R0 ;取显示数字
MOVC A,@A+DPTR
MOV P2,A ;显示年月日
LCALL DELAY ;调用延时
MOV DPTR,#TABLE
SJMP GO
DIAN2: //再判断是否位第12位,第12位也需要有小数点
CJNE R1,#12,YMD ;若不是第10,12位,跳转YMD
MOV DPTR,#TABLE1
MOV A,@R0 ;取显示数字
MOVC A,@A+DPTR
MOV P2,A ;显示年月日
LCALL DELAY ;调用延时
MOV DPTR,#TABLE
SJMP GO
YMD: //正常输出没小数点的数字
MOV A,@R0 ;取显示数字
MOVC A,@A+DPTR
MOV P2,A ;显示年月日
LCALL DELAY ;调用延时
SJMP GO
//P1口实现时分秒
HMS: MOV A,@R0 ;取显示数字
MOVC A,@A+DPTR
MOV P1,A ;显示时分秒
LCALL DELAY ;调用延时
SJMP GO
GO: INC R1 ;显示位左移
INC R0
CJNE R1,#16,NEXT
RET
//共阳极,0亮1灭,共阴极,1亮0灭
TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,40H ;七段共阴数码管0-9
TABLE1: DB 0BFH,86H,0DBH,0CFH,0E6H,0EDH,0FDH,87H,0FFH,0EFH,40H ;带小数点的七段共阴数码管0-9
;计时程序
TIME_INC:
SEC: INC S ;+1S
MOV R6,S
CJNE R6,#60,INC_END ;满60秒进位
MOV R6,#0
MOV S,R6
SJMP MIN
MIN: INC M ;+1M
MOV R6,M
CJNE R6,#60,INC_END ;满60分钟进位
MOV R6,#0
MOV M,R6
SJMP HOUR
HOUR: INC H ;+1H
MOV R6,H
CJNE R6,#24,INC_END ;满24小时进位
MOV R6,#0
MOV H,R6
DAY: LCALL CHECK_Y ;检查平闰年
MOV R6,FLAG
CJNE R6,#1,PING
MOV DPTR,#R_YEAR ;调用闰年月份表
SJMP YGO
PING: MOV DPTR,#P_YEAR ;调用平年月份表
YGO: MOV A,MOU
MOVC A,@A+DPTR
INC A
INC D ;+1D
CJNE A,D,INC_END
MOV R6,#1
MOV D,R6
SJMP MOUN
MOUN: INC MOU ;+1M
MOV R6,MOU
CJNE R6,#13,INC_END ;第13个月进位
MOV R6,#0
MOV MOU,R6
SJMP YEAR
YEAR:
INC YL ;+1Y低位
MOV R6,YL
CJNE R6,#100,INC_END
MOV R6,#0
MOV YL,R6
INC YH ;+1Y高位
MOV R6,YH
CJNE R6,#100,INC_END
MOV R6,#0
MOV YH,R6
INC_END:
RET
;检查平闰年子程序
CHECK_Y:
MOV A,YL
MOV B,#4
DIV AB
MOV A,B
JNZ SET_FLAG
MOV FLAG,#1
SJMP CHECK_END
SET_FLAG:
MOV FLAG,#0
CHECK_END:
RET
P_YEAR: DB 0,31,28,31,30,31,30,31,31,30,31,30,31 ;平年月份表
R_YEAR: DB 0,31,29,31,30,31,30,31,31,30,31,30,31 ;闰年月份表
;将暂存区中的数据转为BCD码存入显示缓冲区
SEND_TO_DIS:
MOV A,ST
LCALL H2B
MOV SDL,R4
MOV SDH,R5 ;存秒
MOV A,MT
LCALL H2B
MOV MDL,R4
MOV MDH,R5 ;存分
MOV A,HT
LCALL H2B
MOV HDL,R4
MOV HDH,R5 ;存时
MOV A,DT
LCALL H2B
MOV DDL,R4
MOV DDH,R5 ;存天
MOV A,MOUT
LCALL H2B
MOV MOUDL,R4
MOV MOUDH,R5 ;存月
MOV A,YLT
LCALL H2B
MOV YD0,R4
MOV YD1,R5 ;存年(低位)
MOV A,YHT
LCALL H2B
MOV YD2,R4
MOV YD3,R5 ;存年(高位)
RET
;1ms延时子程序
DELAY:
MOV R3,#4
DEL: MOV R2,#250
DJNZ R2,$
DJNZ R3,DEL
RET
;
H2B: MOV B,#10
DIV AB
MOV R5,A ;个位存到R5
MOV R4,B ;十位存到R4
RET
;查询按键子程序
CHECK_KEY:
MOV A,P3 ;读取P3按键状态
CPL A;
JZ CHECK_EXIT
ACALL KEY_DELAY
MOV A,P3 ;读取P3按键状态 确认是否有键按下
CPL A
JZ CHECK_EXIT
JB ACC.0,ACT0 ;暂停/恢复键
JB ACC.1,ACT1 ;闹钟键
JB ACC.2,ACT2 ;换位键
JB ACC.3,ACT3 ;+
JB ACC.4,ACT4 ;-
CHECK_EXIT:
RET
;按键子程序
ACT:
ACT0: MOV A,P3 ;检测按键是否释放
JNB ACC.0,ACT0 ;键未释放,则继续等待
CPL K0 ;K0取反,在暂停/继续中转换
JB K0,START
CLR TR0 ;TR0=0,停止计时
LJMP EXIT
START: SETB TR0 ;TRO=1,开始计时
CLR K1 ;默认回修改功能
RET
;定时/修改按钮
ACT1: MOV A,P3 ;检测按键是否释放
JNB ACC.1,ACT1 ;键未释放,则继续等待
CPL K2 ;取反闹铃使能开关
JB K0,EXIT ;若K0未在暂停状态,则返回
CPL K1 ;K1取反,0为修改,1为闹钟定时
RET
;移位按钮
ACT2:
MOV A,P3 ;检测按键是否释放
JNB ACC.2,ACT2 ;键未释放,则继续等待
JB K0,EXIT ;若K0未在暂停状态,则返回
MOV A,SPT
RL A ;SPT移动(RL循环左移,RLC带进位左移,RL不带进位)
MOV SPT,A
JNB ACC.7,EXIT ;最多移到01000000
MOV SPT,#1
RET
;加
ACT3: MOV A,P3 ;检测按键是否释放
JNB ACC.3,ACT3 ;键未释放,则继续等待
JB K0,EXIT ;若K0未在暂停状态,则返回
JB K1,CL_INC
SJMP UP_INC
RET
CL_INC: ;闹钟
LCALL KEY_INC
LCALL SEND_TO_DIS
LCALL SEND1
RET
UP_INC: LCALL SAVE0
LCALL KEY_INC
LCALL SEND_TO_DIS
LCALL SEND0
RET
;减
ACT4: MOV A,P3 ;检测按键是否释放
JNB ACC.4,ACT4 ;键未释放,则继续等待
JB K0,EXIT ;若K0未在暂停状态,则返回
JB K1,CL_DEC
SJMP UP_DEC
RET
CL_DEC: ;闹钟
LCALL KEY_DEC
LCALL SEND_TO_DIS
LCALL SEND1
RET
UP_DEC: LCALL SAVE0
LCALL KEY_DEC
LCALL SEND_TO_DIS
LCALL SEND0
RET
EXIT: RET
KEY_DELAY:
MOV R3,#24
KEY_DEL:MOV R2,#0FAH
DJNZ R2,$
DJNZ R3,KEY_DEL
RET
;数据转移子程序
SAVE0: MOV ST,S
MOV MT,M
MOV HT,H
MOV DT,D
MOV MOUT,MOU
MOV YLT,YL
MOV YHT,YH
RET
;将数据传给计时数据寄存器
SEND0: MOV S,ST
MOV M,MT
MOV H,HT
MOV D,DT
MOV MOU,MOUT
MOV YL,YLT
MOV YH,YHT
RET
;将数据传给闹钟数据寄存器
SEND1: MOV SC,ST
MOV MC,MT
MOV HC,HT
MOV DC,DT
MOV MOUC,MOUT
MOV YLC,YLT
MOV YHC,YHT
RET
//按下按键年月日时分秒的加减处理
;+按键子程序
KEY_INC:
JB SPT.0,S_INC ;未按换位键 默认更改秒
JB SPT.1,M_INC ;按一次更改分
JB SPT.2,H_INC ;按两次更改小时
JB SPT.3,D_INC ;按三次更改日
JB SPT.4,MOU_INC ;按四次更改月
JB SPT.5,YL_INC ;按五次更改年的个十位
JB SPT.6,YH_INC ;按六次更改年的百千位
S_INC: INC ST ;+1S
MOV R6,ST
CJNE R6,#60,EXIT_INC
MOV R6,#0
MOV ST,R6
RET
M_INC: INC MT ;+1M
MOV R6,MT
CJNE R6,#60,EXIT_INC
MOV R6,#0
MOV MT,R6
RET
H_INC: INC HT ;+1H
MOV R6,HT
CJNE R6,#24,EXIT_INC
MOV R6,#0
MOV HT,R6
RET
D_INC: LCALL CHECK_Y
MOV R6,FLAG
CJNE R6,#1,PING1
MOV DPTR,#R_YEAR
SJMP YGO1
PING1: MOV DPTR,#P_YEAR ;暂存本月天数上限
YGO1: MOV A,MOUT
MOVC A,@A+DPTR
INC A
INC DT ;+1D
CJNE A,DT,EXIT_INC
MOV R6,#1
MOV DT,R6
RET
MOU_INC:
INC MOUT ;+1M
MOV R6,MOUT
CJNE R6,#13,EXIT_INC
MOV R6,#1
MOV MOUT,R6
RET
YL_INC: INC YLT ;+1Y低位
MOV R6,YLT
CJNE R6,#100,EXIT_INC
MOV R6,#0
MOV YLT,R6
RET
YH_INC: INC YHT ;+1Y高位
MOV R6,YHT
CJNE R6,#100,EXIT_INC
MOV R6,#0
MOV YHT,R6
RET
EXIT_INC:
RET
;-按键子程序
KEY_DEC:
//根据移位指针SPT哪一位是1
JB SPT.0,S_DEC ;未按换位键 默认更改秒
JB SPT.1,M_DEC ;按一次更改分
JB SPT.2,H_DEC ;按两次更改小时
JB SPT.3,D_DEC ;按三次更改日
JB SPT.4,MOU_DEC ;按四次更改月
JB SPT.5,YL_DEC ;按五次更改年的个十位
JB SPT.6,YH_DEC ;按六次更改年的百千位
S_DEC:
DEC ST ;-1s
MOV R6,ST
CJNE R6,#0FFH,EXIT_DEC
MOV R6,#59
MOV ST,R6
RET
M_DEC:
DEC MT ;-1m
MOV R6,MT
CJNE R6,#0FFH,EXIT_DEC
MOV R6,#59
MOV MT,R6
RET
H_DEC:
DEC HT ;-1h
MOV R6,HT
CJNE R6,#0FFH,EXIT_DEC
MOV R6,#23
MOV HT,R6
RET
D_DEC: LCALL CHECK_Y
MOV R6,FLAG
CJNE R6,#1,PING2
MOV DPTR,#R_YEAR
SJMP YGO2
PING2: MOV DPTR,#P_YEAR
YGO2: MOV A,MOUT
MOVC A,@A+DPTR ;暂存本月天数上限
DEC DT ;-1D
MOV R6,DT
CJNE R6,#0,EXIT_INC
MOV R6,A
MOV DT,R6
RET
MOU_DEC:
DEC MOUT ;-1MO
MOV R6,MOUT
CJNE R6,#0,EXIT_DEC
MOV R6,#12
MOV MOUT,R6
RET
YL_DEC:
DEC YLT ;-1Y(低位)
MOV R6,YLT
CJNE R6,#0FFH,EXIT_DEC
MOV R6,#99
MOV YLT,R6
RET
YH_DEC:
DEC YHT ;-1Y(低位)
MOV R6,YHT
CJNE R6,#0FFH,EXIT_DEC
MOV R6,#99
MOV YHT,R6
RET
EXIT_DEC:
RET
;闹钟响铃子程序
CHECK_CLOCK: ;判断是否响铃
MOV R0,#M
MOV R1,#MC
MOV R2,#5
CHECK_NEXT: ;
MOV A,@R0
SUBB A,@R1 ;判断当前时刻是否是闹铃时刻
CLR C
JNZ CLOC_EXIT
INC R0
INC R1
DJNZ R2,CHECK_NEXT
LCALL TIMEOUT ;分 时 日 月 年均满足则调用响铃程序
RET
CLOC_EXIT:
CLR P3.5
RET
;响铃程序
TIMEOUT:
JNB K2,BUZ_END ;按下按键停止响铃
BUZ: SETB P3.5
LCALL BUZ_DELAY
BUZ_DELAY: ;延时
MOV R3,#250
BUZ_T: MOV R2,#40
DJNZ R2,$
DJNZ R3,BUZ_T
RET
BUZ_END:
CLR P3.5
RET
;亮灯子程序
LIGHT_ON:
MOV A,#12
CJNE A,H,TTE3
MOV A,#00
CJNE A,M,TTE3
MOV A,#00
CJNE A,S,TTE3
SETB P3.6 ;从12:00:00开始亮
TTE3:
RET
LIGHT_OFF:
MOV A,#23;CMP_LED_START
CJNE A,H,TTE4
MOV A,#00
CJNE A,M,TTE4
MOV A,#00
CJNE A,S,TTE4
CLR P3.6 ;到21:00:00关灯
TTE4:
RET
END
R_YEAR: DB 0,31,29,31,30,31,30,31,31,30,31,30,31 ;
TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,40H ;
END
电路图:
汇编代码:
ORG 0000H
LJMP MAIN
ORG 000BH
LJMP TIME
ORG 0100H
;宏定义
;键位
K0 BIT 20H.0
K1 BIT 20H.1
K2 BIT 20H.2
K3 BIT 20H.3
K4 BIT 20H.4
;暂存区
ST DATA 68H
MT DATA 69H
HT DATA 6AH
DT DATA 6BH
MOUT DATA 6CH
YLT DATA 6DH
YHT DATA 6EH
SPT DATA 21H ;移位指针
;时钟时间寄存区
S DATA 60H
M DATA 61H
H DATA 62H
D DATA 63H
MOU DATA 64H
YL DATA 65H
YH DATA 66H
FLAG DATA 67H
;闹钟时间寄存区
SC DATA 50H
MC DATA 51H
HC DATA 52H
DC DATA 53H
MOUC DATA 54H
YLC DATA 55H
YHC DATA 56H
;时间显示缓冲区
//存放数码管显示16位的数据
SDL DATA 70H
SDH DATA 71H
POINT1 DATA 72H
MDL DATA 73H
MDH DATA 74H
POINT2 DATA 75H
HDL DATA 76H
HDH DATA 77H
DDL DATA 78H
DDH DATA 79H
MOUDL DATA 7AH
MOUDH DATA 7BH
YD0 DATA 7CH
YD1 DATA 7DH
YD2 DATA 7EH
YD3 DATA 7FH
//主程序
MAIN:
MOV TMOD,#01H ;T0工作方式1
MOV TL0,#0B0H
MOV TH0,#3CH ;50ms
MOV R7,#20 ;20*50ms = 1s
MOV S,#50
MOV M,#59
MOV H,#11
MOV D,#11
MOV MOU,#12
MOV YL,#20
MOV YH,#20
MOV POINT1,#10 ;在TABLE中第10个对应“-”
MOV POINT2,#10
MOV SPT,#1 ;移位指针初始最低位为1
SETB K0
CLR K1 ;K1置1 (非暂停状态)
CLR K2 ;K2置1 默认修改模式
CLR P3.5 ;默认蜂鸣器非工作状态
CLR P3.6 ;默认LED非工作状态
SETB ET0
SETB EA
SETB TR0 ;开启定时器
;不断循环
GO_ON:
LCALL CHECK_KEY
LCALL DISPLAY
LCALL CHECK_CLOCK ;闹铃
LCALL LIGHT_ON ;开灯
LCALL LIGHT_OFF ;关灯
SJMP GO_ON ;跳转循环
;定时子程序
TIME:
MOV TL0,#0B0H
MOV TH0,#3CH
DJNZ R7,TIME_END
MOV R7,#20 ;循环20次 定时1s
LCALL TIME_INC ;跳转到计时
LCALL SAVE0 ;跳转到数据转移
LCALL SEND_TO_DIS ;储存时间寄存器中的BCD
TIME_END:
RETI
;数码管显示子程序
DISPLAY:
MOV R0,#SDL ;数据缓存区指针
MOV DPTR,#TABLE ;七段共阴数码管0-9显示
MOV R1,#0 ;R1存放表示第几位的数字
//P0口实现片选
NEXT: MOV P0,R1 ;显示位连接P0
MOV A,R1
CLR C
SUBB A,#8 //实现前8个向HMS跳转,后8个向YMD跳转
JC HMS
//P2口实现年月日
DIAN1: //先判断是否位第10位,第10位需要有小数点
CJNE R1,#10,DIAN2 ;跳转判断DIAN2
MOV DPTR,#TABLE1
MOV A,@R0 ;取显示数字
MOVC A,@A+DPTR
MOV P2,A ;显示年月日
LCALL DELAY ;调用延时
MOV DPTR,#TABLE
SJMP GO
DIAN2: //再判断是否位第12位,第12位也需要有小数点
CJNE R1,#12,YMD ;若不是第10,12位,跳转YMD
MOV DPTR,#TABLE1
MOV A,@R0 ;取显示数字
MOVC A,@A+DPTR
MOV P2,A ;显示年月日
LCALL DELAY ;调用延时
MOV DPTR,#TABLE
SJMP GO
YMD: //正常输出没小数点的数字
MOV A,@R0 ;取显示数字
MOVC A,@A+DPTR
MOV P2,A ;显示年月日
LCALL DELAY ;调用延时
SJMP GO
//P1口实现时分秒
HMS: MOV A,@R0 ;取显示数字
MOVC A,@A+DPTR
MOV P1,A ;显示时分秒
LCALL DELAY ;调用延时
SJMP GO
GO: INC R1 ;显示位左移
INC R0
CJNE R1,#16,NEXT
RET
//共阳极,0亮1灭,共阴极,1亮0灭
TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,40H ;七段共阴数码管0-9
TABLE1: DB 0BFH,86H,0DBH,0CFH,0E6H,0EDH,0FDH,87H,0FFH,0EFH,40H ;带小数点的七段共阴数码管0-9
;计时程序
TIME_INC:
SEC: INC S ;+1S
MOV R6,S
CJNE R6,#60,INC_END ;满60秒进位
MOV R6,#0
MOV S,R6
SJMP MIN
MIN: INC M ;+1M
MOV R6,M
CJNE R6,#60,INC_END ;满60分钟进位
MOV R6,#0
MOV M,R6
SJMP HOUR
HOUR: INC H ;+1H
MOV R6,H
CJNE R6,#24,INC_END ;满24小时进位
MOV R6,#0
MOV H,R6
DAY: LCALL CHECK_Y ;检查平闰年
MOV R6,FLAG
CJNE R6,#1,PING
MOV DPTR,#R_YEAR ;调用闰年月份表
SJMP YGO
PING: MOV DPTR,#P_YEAR ;调用平年月份表
YGO: MOV A,MOU
MOVC A,@A+DPTR
INC A
INC D ;+1D
CJNE A,D,INC_END
MOV R6,#1
MOV D,R6
SJMP MOUN
MOUN: INC MOU ;+1M
MOV R6,MOU
CJNE R6,#13,INC_END ;第13个月进位
MOV R6,#0
MOV MOU,R6
SJMP YEAR
YEAR:
INC YL ;+1Y低位
MOV R6,YL
CJNE R6,#100,INC_END
MOV R6,#0
MOV YL,R6
INC YH ;+1Y高位
MOV R6,YH
CJNE R6,#100,INC_END
MOV R6,#0
MOV YH,R6
INC_END:
RET
;检查平闰年子程序
CHECK_Y:
MOV A,YL
MOV B,#4
DIV AB
MOV A,B
JNZ SET_FLAG
MOV FLAG,#1
SJMP CHECK_END
SET_FLAG:
MOV FLAG,#0
CHECK_END:
RET
P_YEAR: DB 0,31,28,31,30,31,30,31,31,30,31,30,31 ;平年月份表
R_YEAR: DB 0,31,29,31,30,31,30,31,31,30,31,30,31 ;闰年月份表
;将暂存区中的数据转为BCD码存入显示缓冲区
SEND_TO_DIS:
MOV A,ST
LCALL H2B
MOV SDL,R4
MOV SDH,R5 ;存秒
MOV A,MT
LCALL H2B
MOV MDL,R4
MOV MDH,R5 ;存分
MOV A,HT
LCALL H2B
MOV HDL,R4
MOV HDH,R5 ;存时
MOV A,DT
LCALL H2B
MOV DDL,R4
MOV DDH,R5 ;存天
MOV A,MOUT
LCALL H2B
MOV MOUDL,R4
MOV MOUDH,R5 ;存月
MOV A,YLT
LCALL H2B
MOV YD0,R4
MOV YD1,R5 ;存年(低位)
MOV A,YHT
LCALL H2B
MOV YD2,R4
MOV YD3,R5 ;存年(高位)
RET
;1ms延时子程序
DELAY:
MOV R3,#4
DEL: MOV R2,#250
DJNZ R2,$
DJNZ R3,DEL
RET
;
H2B: MOV B,#10
DIV AB
MOV R5,A ;个位存到R5
MOV R4,B ;十位存到R4
RET
;查询按键子程序
CHECK_KEY:
MOV A,P3 ;读取P3按键状态
CPL A;
JZ CHECK_EXIT
ACALL KEY_DELAY
MOV A,P3 ;读取P3按键状态 确认是否有键按下
CPL A
JZ CHECK_EXIT
JB ACC.0,ACT0 ;暂停/恢复键
JB ACC.1,ACT1 ;闹钟键
JB ACC.2,ACT2 ;换位键
JB ACC.3,ACT3 ;+
JB ACC.4,ACT4 ;-
CHECK_EXIT:
RET
;按键子程序
ACT:
ACT0: MOV A,P3 ;检测按键是否释放
JNB ACC.0,ACT0 ;键未释放,则继续等待
CPL K0 ;K0取反,在暂停/继续中转换
JB K0,START
CLR TR0 ;TR0=0,停止计时
LJMP EXIT
START: SETB TR0 ;TRO=1,开始计时
CLR K1 ;默认回修改功能
RET
;定时/修改按钮
ACT1: MOV A,P3 ;检测按键是否释放
JNB ACC.1,ACT1 ;键未释放,则继续等待
CPL K2 ;取反闹铃使能开关
JB K0,EXIT ;若K0未在暂停状态,则返回
CPL K1 ;K1取反,0为修改,1为闹钟定时
RET
;移位按钮
ACT2:
MOV A,P3 ;检测按键是否释放
JNB ACC.2,ACT2 ;键未释放,则继续等待
JB K0,EXIT ;若K0未在暂停状态,则返回
MOV A,SPT
RL A ;SPT移动(RL循环左移,RLC带进位左移,RL不带进位)
MOV SPT,A
JNB ACC.7,EXIT ;最多移到01000000
MOV SPT,#1
RET
;加
ACT3: MOV A,P3 ;检测按键是否释放
JNB ACC.3,ACT3 ;键未释放,则继续等待
JB K0,EXIT ;若K0未在暂停状态,则返回
JB K1,CL_INC
SJMP UP_INC
RET
CL_INC: ;闹钟
LCALL KEY_INC
LCALL SEND_TO_DIS
LCALL SEND1
RET
UP_INC: LCALL SAVE0
LCALL KEY_INC
LCALL SEND_TO_DIS
LCALL SEND0
RET
;减
ACT4: MOV A,P3 ;检测按键是否释放
JNB ACC.4,ACT4 ;键未释放,则继续等待
JB K0,EXIT ;若K0未在暂停状态,则返回
JB K1,CL_DEC
SJMP UP_DEC
RET
CL_DEC: ;闹钟
LCALL KEY_DEC
LCALL SEND_TO_DIS
LCALL SEND1
RET
UP_DEC: LCALL SAVE0
LCALL KEY_DEC
LCALL SEND_TO_DIS
LCALL SEND0
RET
EXIT: RET
KEY_DELAY:
MOV R3,#24
KEY_DEL:MOV R2,#0FAH
DJNZ R2,$
DJNZ R3,KEY_DEL
RET
;数据转移子程序
SAVE0: MOV ST,S
MOV MT,M
MOV HT,H
MOV DT,D
MOV MOUT,MOU
MOV YLT,YL
MOV YHT,YH
RET
;将数据传给计时数据寄存器
SEND0: MOV S,ST
MOV M,MT
MOV H,HT
MOV D,DT
MOV MOU,MOUT
MOV YL,YLT
MOV YH,YHT
RET
;将数据传给闹钟数据寄存器
SEND1: MOV SC,ST
MOV MC,MT
MOV HC,HT
MOV DC,DT
MOV MOUC,MOUT
MOV YLC,YLT
MOV YHC,YHT
RET
//按下按键年月日时分秒的加减处理
;+按键子程序
KEY_INC:
JB SPT.0,S_INC ;未按换位键 默认更改秒
JB SPT.1,M_INC ;按一次更改分
JB SPT.2,H_INC ;按两次更改小时
JB SPT.3,D_INC ;按三次更改日
JB SPT.4,MOU_INC ;按四次更改月
JB SPT.5,YL_INC ;按五次更改年的个十位
JB SPT.6,YH_INC ;按六次更改年的百千位
S_INC: INC ST ;+1S
MOV R6,ST
CJNE R6,#60,EXIT_INC
MOV R6,#0
MOV ST,R6
RET
M_INC: INC MT ;+1M
MOV R6,MT
CJNE R6,#60,EXIT_INC
MOV R6,#0
MOV MT,R6
RET
H_INC: INC HT ;+1H
MOV R6,HT
CJNE R6,#24,EXIT_INC
MOV R6,#0
MOV HT,R6
RET
D_INC: LCALL CHECK_Y
MOV R6,FLAG
CJNE R6,#1,PING1
MOV DPTR,#R_YEAR
SJMP YGO1
PING1: MOV DPTR,#P_YEAR ;暂存本月天数上限
YGO1: MOV A,MOUT
MOVC A,@A+DPTR
INC A
INC DT ;+1D
CJNE A,DT,EXIT_INC
MOV R6,#1
MOV DT,R6
RET
MOU_INC:
INC MOUT ;+1M
MOV R6,MOUT
CJNE R6,#13,EXIT_INC
MOV R6,#1
MOV MOUT,R6
RET
YL_INC: INC YLT ;+1Y低位
MOV R6,YLT
CJNE R6,#100,EXIT_INC
MOV R6,#0
MOV YLT,R6
RET
YH_INC: INC YHT ;+1Y高位
MOV R6,YHT
CJNE R6,#100,EXIT_INC
MOV R6,#0
MOV YHT,R6
RET
EXIT_INC:
RET
;-按键子程序
KEY_DEC:
//根据移位指针SPT哪一位是1
JB SPT.0,S_DEC ;未按换位键 默认更改秒
JB SPT.1,M_DEC ;按一次更改分
JB SPT.2,H_DEC ;按两次更改小时
JB SPT.3,D_DEC ;按三次更改日
JB SPT.4,MOU_DEC ;按四次更改月
JB SPT.5,YL_DEC ;按五次更改年的个十位
JB SPT.6,YH_DEC ;按六次更改年的百千位
S_DEC:
DEC ST ;-1s
MOV R6,ST
CJNE R6,#0FFH,EXIT_DEC
MOV R6,#59
MOV ST,R6
RET
M_DEC:
DEC MT ;-1m
MOV R6,MT
CJNE R6,#0FFH,EXIT_DEC
MOV R6,#59
MOV MT,R6
RET
H_DEC:
DEC HT ;-1h
MOV R6,HT
CJNE R6,#0FFH,EXIT_DEC
MOV R6,#23
MOV HT,R6
RET
D_DEC: LCALL CHECK_Y
MOV R6,FLAG
CJNE R6,#1,PING2
MOV DPTR,#R_YEAR
SJMP YGO2
PING2: MOV DPTR,#P_YEAR
YGO2: MOV A,MOUT
MOVC A,@A+DPTR ;暂存本月天数上限
DEC DT ;-1D
MOV R6,DT
CJNE R6,#0,EXIT_INC
MOV R6,A
MOV DT,R6
RET
MOU_DEC:
DEC MOUT ;-1MO
MOV R6,MOUT
CJNE R6,#0,EXIT_DEC
MOV R6,#12
MOV MOUT,R6
RET
YL_DEC:
DEC YLT ;-1Y(低位)
MOV R6,YLT
CJNE R6,#0FFH,EXIT_DEC
MOV R6,#99
MOV YLT,R6
RET
YH_DEC:
DEC YHT ;-1Y(低位)
MOV R6,YHT
CJNE R6,#0FFH,EXIT_DEC
MOV R6,#99
MOV YHT,R6
RET
EXIT_DEC:
RET
;闹钟响铃子程序
CHECK_CLOCK: ;判断是否响铃
MOV R0,#M
MOV R1,#MC
MOV R2,#5
CHECK_NEXT: ;
MOV A,@R0
SUBB A,@R1 ;判断当前时刻是否是闹铃时刻
CLR C
JNZ CLOC_EXIT
INC R0
INC R1
DJNZ R2,CHECK_NEXT
LCALL TIMEOUT ;分 时 日 月 年均满足则调用响铃程序
RET
CLOC_EXIT:
CLR P3.5
RET
;响铃程序
TIMEOUT:
JNB K2,BUZ_END ;按下按键停止响铃
BUZ: SETB P3.5
LCALL BUZ_DELAY
BUZ_DELAY: ;延时
MOV R3,#250
BUZ_T: MOV R2,#40
DJNZ R2,$
DJNZ R3,BUZ_T
RET
BUZ_END:
CLR P3.5
RET
;亮灯子程序
LIGHT_ON:
MOV A,#12
CJNE A,H,TTE3
MOV A,#00
CJNE A,M,TTE3
MOV A,#00
CJNE A,S,TTE3
SETB P3.6 ;从12:00:00开始亮
TTE3:
RET
LIGHT_OFF:
MOV A,#23;CMP_LED_START
CJNE A,H,TTE4
MOV A,#00
CJNE A,M,TTE4
MOV A,#00
CJNE A,S,TTE4
CLR P3.6 ;到21:00:00关灯
TTE4:
RET
END
R_YEAR: DB 0,31,29,31,30,31,30,31,31,30,31,30,31 ;
TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,40H ;
END
举报