📄 clock.asm
字号:
SCL EQU P1.2
SDA EQU P1.3
ORG 0000H
AJMP MAIN
ORG 000BH
AJMP TIME
ORG 0300H
MAIN:
MOV 20H,#00H ;25ms定时计数器
MOV 21H,#50H ;秒
MOV 22H,#30H ;分
MOV 23H,#12H ;时
MOV 24H,#08H ;日
MOV 25H,#06H ;月
MOV 26H,#07H ;
MOV 27H,#20H ;年
MOV 30H,#00H ;当30H里的值为00H时,数码管显示时间;
;当30H里的值为0FFH时,数码管显示日期;
;默认显示时间
MOV 31H,#00H ;但31H里的值为00H时,闹钟关闭
;但31H里的值为0FFH时,闹钟打开
;默认为关闭,通过按键P3.7打开
MOV 32H,#00H ;若32H为0FFH,则启动闹钟计数器,使闹钟响5秒
MOV 33H,#00H ;闹钟计数器
MOV 34H,#00H ;闹钟调整:若为0FFH则进入调整,使数码管显示闹钟时刻
MOV 40H,#00H ;闹钟,分
MOV 41H,#00H ;闹钟,时
MOV A,#00H ;24c02的读地址,读到数据为分
LCALL RD24
MOV 40H,A
NOP
MOV A,#01H ;读地址,读到数据为时
LCALL RD24
MOV 41H,A
MOV IP,#02H ;设置中断优先级
MOV IE,#82H ;设置中断允许
MOV TMOD,#01H ;设置定时器T0的工作方式,16位计数器
MOV TL0,#00H ;定时器的间隔为25ms,初值为A600H,晶振频率为11.0592MHz
MOV TH0,#0A6H
SETB TR0 ;启动定时器T0
MOV SP,#50H ;重新设置堆栈指针
CLR P1.0
NEXT:
MOV A,31H ;判断是否允许闹钟
CJNE A,#0FFH,NOSPEAKER
LCALL NAOZHONG
MOV A,32H ;判断是否到了闹钟时刻
CJNE A,#0FFH,NOSPEAKER
LCALL SPEAKER
NOSPEAKER:
MOV A,31H ;闹钟开,LED灯点亮
CJNE A,#0FFH,N_LED
CLR P1.1
AJMP LED_END
N_LED:
SETB P1.1
LED_END:
;检测是否有按键按下
LCALL KEY
;MOV A,R6
JNZ ANSKEY ;P3口有按键按下
MOV A,B
JZ DISP ;P1口没有按键按下
MOV A,#00H
ANSKEY:
LCALL ANKEY
DISP:
MOV A,34H
JNZ G2
MOV A,30H
JNZ G0 ;显示年、月、日
LCALL DISP2 ;调用时、分、秒显示子程序
SJMP G1
G0:
LCALL DISP1 ;调用年、月、日显示子程序
SJMP G1
G2:
LCALL DISP3 ;显示闹钟时刻
G1:
SJMP NEXT ;循环显示
;主程序结束
;定时器处理子程序
TIME:
PUSH ACC
PUSH PSW
MOV TL0,#00H ;重置定时器初值
MOV TH0,#0A6H
INC 20H
MOV A,20H
CJNE A,#40,RETITIME ;如果25ms计数器的值为40时,即1秒到
MOV 20H,#00H
;--------------------------------------------
;闹钟计数器处理模块
MOV A,32H
CJNE A,#0FFH,N_NAOZHONG
MOV A,33H
INC A
MOV 33H,A
CJNE A,#05H,N_NAOZHONG
MOV 31H,#00H
MOV 32H,#00H
MOV 33H,#00H
N_NAOZHONG:
;--------------------------------------------
MOV A,21H ;秒处理
ADD A,#01H
DA A
MOV 21H,A
CJNE A,#60H,RETITIME ;1分到
MOV 21H,#00H
MOV A,22H ;分处理
ADD A,#01H
DA A
MOV 22H,A
CJNE A,#60H,RETITIME ;1时到
MOV 22H,#00H
MOV A,23H ;时处理
ADD A,#01H
DA A
MOV 23H,A
CJNE A,#24H,RETITIME ;1天到
MOV 23H,#00H
MOV A,24H ;天处理
ADD A,#01H
DA A
MOV 24H,A
ACALL MONTH
CJNE A,24H,RETITIME ;1月到
MOV 24H,#01H
MOV A,25H ;月处理
ADD A,#01H
DA A
MOV 25H,A
CJNE A,#13H,RETITIME ;1年到
MOV 25H,#01H
MOV A,26H ;年处理
CJNE A,#99H,NO_OH_YEAR ;
MOV 26H,#00H ;100年到
AJMP OH_YEAR
NO_OH_YEAR:
ADD A,#01H
DA A
MOV 26H,A
AJMP RETITIME
OH_YEAR:
MOV A,27H
ADD A,#01H
DA A
MOV 27H,A
RETITIME:
POP PSW
POP ACC
RETI ;时间处理子程序结束
;月份处理子程序,返回值为当前月份数,存在A中
MONTH:
MOV A,25H
XRL A,#01H
JZ LAB1 ;一月
MOV A,25H
XRL A,#02H
JZ LAB2
MOV A,25H
XRL A,#03H
JZ LAB1
MOV A,25H
XRL A,#04H
JZ LAB3
MOV A,25H
XRL A,#05H
JZ LAB1
MOV A,25H
XRL A,#06H
JZ LAB3
MOV A,25H
XRL A,#07H
JZ LAB1
MOV A,25H
XRL A,#08H
JZ LAB1
MOV A,25H
XRL A,#09H
JZ LAB3
MOV A,25H
XRL A,#10H
JZ LAB1
MOV A,25H
XRL A,#11H
JZ LAB3
MOV A,25H
XRL A,#12H
LAB1:
MOV A,#32H
AJMP RETMONTH
LAB2:
MOV A,#29H
AJMP RETMONTH
LAB3:
MOV A,#31H
RETMONTH:
RET ;月份处理子程序结束
;年、月、日显示子程序
DISP1:
MOV A,24H ;处理日数
ANL A,#0FH
MOV 2FH,A ;2FH里为日的低4位译码
MOV A,24H
ANL A,#0F0H
SWAP A
MOV 2EH,A ;2EH里为日的高4位译码
MOV A,25H ;处理月数
ANL A,#0FH
MOV 2DH,A
MOV A,25H
ANL A,#0F0H
SWAP A
MOV 2CH,A
MOV A,26H ;处理年数
ANL A,#0FH
MOV 2BH,A
MOV A,26H
ANL A,#0F0H
SWAP A
MOV 2AH,A
MOV A,27H
ANL A,#0FH
MOV 29H,A
MOV A,27H
ANL A,#0F0H
SWAP A
MOV 28H,A
;对显示数据译码
MOV R0,#2FH ;显示数据的地址为:2FH--28H
MOV R3,#08H ;显示在8个数码管上
MOV DPTR,#TABLE
MOV A,#80H ;显示数码管地址
LOOP1:
MOV B,A
MOV P2,A ;送出数码管地址
MOV A,@R0
MOVC A,@A+DPTR
MOV P0,A
MOV R2,#40H ;延时
DJNZ R2,$ ;在当前位置循环
DEC R0 ;指向下一个显示数据地址
MOV A,B
RR A ;改变数码管显示地址
DJNZ R3,LOOP1
RET ;年、月、日显示子程序结束
;时、分、秒显示子程序
DISP2:
MOV A,21H ;秒处理
ANL A,#0FH
MOV 2FH,A ;低4位存在2FH里
MOV A,21H
ANL A,#0F0H
SWAP A
MOV 2EH,A
MOV 2DH,#0AH ;显示一个“-”
MOV A,22H ;分处理
ANL A,#0FH
MOV 2CH,A
MOV A,22H
ANL A,#0F0H
SWAP A
MOV 2BH,A
MOV 2AH,#0AH ;显示一个“-”
MOV A,23H ;时处理
ANL A,#0FH
MOV 29H,A
MOV A,23H
ANL A,#0F0H
SWAP A
MOV 28H,A
;对显示数据译码
MOV R0,#2FH
MOV R3,#08H
MOV DPTR,#TABLE
MOV A,#80H
LOOP2:
MOV B,A
MOV P2,A
MOV A,@R0
MOVC A,@A+DPTR
MOV P0,A
MOV R2,#40H
DJNZ R2,$
DEC R0
MOV A,B
RR A
DJNZ R3,LOOP2
RET ;时、分、秒显示子程序结束
;闹钟时刻显示子程序
DISP3:
MOV 2FH,#0BH ;秒位置的数码管灭
MOV 2EH,#0BH
MOV 2DH,#0BH
MOV A,40H ;分处理
ANL A,#0FH
MOV 2CH,A
MOV A,40H
ANL A,#0F0H
SWAP A
MOV 2BH,A
MOV 2AH,#0AH ;显示一个“-”
MOV A,41H ;时处理
ANL A,#0FH
MOV 29H,A
MOV A,41H
ANL A,#0F0H
SWAP A
MOV 28H,A
;对显示数据译码
MOV R0,#2FH
MOV R3,#08H
MOV DPTR,#TABLE
MOV A,#80H
LOOP3:
MOV B,A
MOV P2,A
MOV A,@R0
MOVC A,@A+DPTR
MOV P0,A
MOV R2,#40H
DJNZ R2,$
DEC R0
MOV A,B
RR A
DJNZ R3,LOOP3
RET ;时、分、秒显示子程序结束
TABLE: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,0BFH,0FFH ;0,1,2,3,4,5,6,7,8,9,-, ;
;清除数码管显示子程序
CLEAR:
MOV R3,#08H
MOV A,#80H
LOOP4:
MOV B,A
MOV P2,A
MOV P0,#0FFH
MOV A,B
RR A
DJNZ R3,LOOP4
RET ;清除数码管显示子程序结束
;按键扫描子程序(思路:连续两次读入按键值,判断是否为按键抖动,然后等待释放按键)
KEY:
ACALL CLEAR ;按下按键时,数码管不显示
MOV P3,#0FFH ;第一次读入按键值
MOV A,P3
CPL A
JZ KEYTIAO ;P3口无按键按下
MOV P3,#0FFH ;第二次读入按键值
MOV A,P3
CPL A
JZ KEYTIAO ;按键抖动,非期望
MOV R6,A ;保存键值
LOOPKEY:
MOV P3,#0FFH ;等待释放按键
MOV A,P3
CPL A
JNZ LOOPKEY
MOV A,R6 ;按键值存在A中
MOV B,#00H
SJMP RETKEY
KEYTIAO:
;MOV P1,#0FFH ;第一次读入按键值
MOV A,P1
CPL A
ANL A,#0C0H
MOV B,A
JZ RETKEY ;P1口无按键按下
;MOV P1,#0FFH ;第二次读入按键值
MOV A,P1
CPL A
ANL A,#0C0H
MOV B,A
JZ RETKEY ;按键抖动,非期望
MOV R5,B ;保存键值
LOOPKEYTIAO:
;MOV P1,#0FFH ;等待释放按键
MOV A,P1
CPL A
ANL A,#0C0H
MOV B,A
JNZ LOOPKEYTIAO
MOV B,R5 ;按键值存在B中
MOV A,#00H
RETKEY:
RET ;按键扫描子程序结束
;按键处理子程序(按键值从A中读入)
ANKEY:
;MOV A,R6
JB ACC.0,K0
JB ACC.1,K1
JB ACC.2,K2
JB ACC.3,K3
JB ACC.4,K4
JB ACC.5,K5
JB ACC.6,K6
JB ACC.7,K7
MOV A,B
JB ACC.6,KT
JB ACC.7,KQ
AJMP RETANKEY
K0:
LCALL KEY0
AJMP RETANKEY
K1:
LCALL KEY1
AJMP RETANKEY
K2:
LCALL KEY2
AJMP RETANKEY
K3:
LCALL KEY3
AJMP RETANKEY
K4:
LCALL KEY4
AJMP RETANKEY
K5:
LCALL KEY5
AJMP RETANKEY
K6:
LCALL KEY6
AJMP RETANKEY
K7:
LCALL KEY7
AJMP RETANKEY
KT:
LCALL KEYTIAOZHENG
AJMP RETANKEY
KQ:
LCALL KEYQUEREN
RETANKEY:
RET ;按键处理子程序结束
;按键P3.0执行的内容:改变30H里的数值,使数码管显示年、月、日或者时、分、秒
KEY0:
MOV A,30H
CPL A
MOV 30H,A
RET ;按键P3.0子程序结束
;按键P3.1执行的内容:年或者时+1
KEY1:
MOV A,30H
CJNE A,#0FFH,TA_HOUR
;进行年+1
MOV A,26H
CJNE A,#99H,TA_NO_OH_YEAR
MOV 26H,#00H
AJMP TA_OH_YEAR
TA_NO_OH_YEAR:
ADD A,#01H
DA A
MOV 26H,A
AJMP RETKEY1
TA_OH_YEAR:
MOV A,27H
ADD A,#01H
DA A
MOV 27H,A
AJMP RETKEY1
;进行时+1
TA_HOUR:
MOV A,34H
JNZ TA_HOUR_NAOZH
;时钟时+1
MOV A,23H
ADD A,#01H
DA A
MOV 23H,A
CJNE A,#24H,RETKEY1
MOV 23H,#00H
AJMP RETKEY1
;闹钟时+1
TA_HOUR_NAOZH:
MOV A,41H
ADD A,#01H
DA A
MOV 41H,A
CJNE A,#24H,RETKEY1
MOV 41H,#00H
RETKEY1:
RET ;按键P3.1子程序结束
;按键P3.2执行的内容::年或者时-1
KEY2:
MOV A,30H
CJNE A,#0FFH,TD_HOUR
;进行年-1
MOV A,26H
CJNE A,#00H,TD_NO_OH_YEAR
MOV 26H,#99H
AJMP TD_OH_YEAR
TD_NO_OH_YEAR:
CLR C
LCALL BCDBIN
SUBB A,#01H
LCALL BINBCD
MOV 26H,A
AJMP RETKEY2
TD_OH_YEAR:
MOV A,27H
LCALL BCDBIN
CLR C
SUBB A,#01H
LCALL BINBCD
MOV 27H,A
AJMP RETKEY2
;进行时-1
TD_HOUR:
MOV A,34H
JNZ TD_HOUR_NAOZH
;时钟时-1
MOV A,23H
CJNE A,#00H,TD_NO_OD
MOV 23H,#23H
AJMP RETKEY2
TD_NO_OD:
LCALL BCDBIN
CLR C
SUBB A,#01H
LCALL BINBCD
MOV 23H,A
AJMP RETKEY2
;闹钟时-1
TD_HOUR_NAOZH:
MOV A,41H
CJNE A,#00H,TD_NO_OD_NAOZH
MOV 41H,#23H
AJMP RETKEY2
TD_NO_OD_NAOZH:
LCALL BCDBIN
CLR C
SUBB A,#01H
LCALL BINBCD
MOV 41H,A
RETKEY2:
RET ;按键P3.2子程序结束
;按键P3.3执行的内容:月或者分+1
KEY3:
MOV A,30H
CJNE A,#0FFH,TA_MIN
;进行月+1
MOV A,25H
ADD A,#01H
DA A
MOV 25H,A
CJNE A,#13H,RETKEY3
MOV 25H,#01H
AJMP RETKEY3
;进行分+1
TA_MIN:
MOV A,34H
JNZ TA_MIN_NAOZH
;时钟分+1
MOV A,22H
ADD A,#01H
DA A
MOV 22H,A
CJNE A,#60H,RETKEY3
MOV 22H,#00H
AJMP RETKEY3
TA_MIN_NAOZH:
;闹钟分+1
MOV A,40H
ADD A,#01H
DA A
MOV 40H,A
CJNE A,#60H,RETKEY3
MOV 40H,#00H
RETKEY3:
RET ;按键P3.3子程序结束
;按键P3.4执行的内容:月或者分-1
KEY4:
MOV A,30H
CJNE A,#0FFH,TD_MIN
;进行月-1
MOV A,25H
CJNE A,#01H,TD_NO_OM
MOV 25H,#12H
AJMP RETKEY4
TD_NO_OM:
CLR C
LCALL BCDBIN
SUBB A,#01H
LCALL BINBCD
MOV 25H,A
AJMP RETKEY4
;进行分-1
TD_MIN:
MOV A,34H
JNZ TD_MIN_NAOZH
;时钟的分-1
MOV A,22H
CJNE A,#00H,TD_NO_OH
MOV 22H,#59H
AJMP RETKEY4
TD_NO_OH:
LCALL BCDBIN
CLR C
SUBB A,#01H
LCALL BINBCD
MOV 22H,A
AJMP RETKEY4
TD_MIN_NAOZH:
;闹钟的分-1
MOV A,40H
CJNE A,#00H,TD_NO_OH_NAOZH
MOV 40H,#59H
AJMP RETKEY4
TD_NO_OH_NAOZH:
LCALL BCDBIN
CLR C
SUBB A,#01H
LCALL BINBCD
MOV 40H,A
RETKEY4:
RET ;按键P3.4子程序结束
;按键P3.5执行的内容:日或者秒+1
KEY5:
MOV A,30H
CJNE A,#0FFH,TA_SEC
;进行日+1
MOV A,24H
ADD A,#01H
DA A
MOV 24H,A
ACALL MONTH
CJNE A,24H,RETKEY5
MOV 24H,#01H
AJMP RETKEY5
;进行秒+1
TA_SEC:
MOV A,21H
ADD A,#01H
DA A
MOV 21H,A
CJNE A,#60H,RETKEY3
MOV 21H,#00H
RETKEY5:
RET ;按键P3.5子程序结束
;按键P3.6执行的内容:日或者秒-1
KEY6:
MOV A,30H
CJNE A,#0FFH,TD_SEC
;进行日-1
MOV A,24H
CJNE A,#01H,TD_NO_ODAY
LCALL MONTH
DEC A
MOV 24H,A
AJMP RETKEY6
TD_NO_ODAY:
CLR C
LCALL BCDBIN
SUBB A,#01H
LCALL BINBCD
MOV 24H,A
AJMP RETKEY4
;进行秒-1
TD_SEC:
MOV A,21H
CJNE A,#00H,TD_NO_OMS
MOV 21H,#59H
AJMP RETKEY6
TD_NO_OMS:
LCALL BCDBIN
CLR C
SUBB A,#01H
LCALL BINBCD
MOV 21H,A
RETKEY6:
RET ;按键P3.6子程序结束
;按键P3.7子程序
KEY7:
MOV A,31H
CPL A
MOV 31H,A
MOV 32H,#00H
MOV 33H,#00H
RET ;按键P3.7子程序结束
;按键P1.6,进入闹钟调整
KEYTIAOZHENG:
MOV 34H,#0FFH
RET
;按键P1.7,确认闹钟调整
KEYQUEREN:
MOV 34H,#00H
;---------------------------
;把闹钟设置写入24c02
;写分
MOV A,40H
MOV B,A
MOV A,#00H
LCALL WT24
;写时
MOV B,41H
MOV A,#01H
LCALL WT24
RET
;BCD码转换成BIN码
BCDBIN:
PUSH B
PUSH PSW
PUSH ACC
ANL A,#0F0H
SWAP A
MOV B,#0AH
MUL AB
MOV B,A
POP ACC
ANL A,#0FH
ADD A,B
POP PSW
POP B
RET
;BIN码转换成BCD码
BINBCD:
PUSH PSW
PUSH B
MOV B,#10
DIV AB
SWAP A
ADD A,B
POP B
POP PSW
RET
;蜂鸣器子程序
SPEAKER:
MOV R0,#0FFH
DJNZ R0,$
SETB P1.0
MOV R0,#0FFH
DJNZ R0,$
CLR P1.0
RET ;蜂鸣器子程序结束
;闹钟子程序
NAOZHONG:
MOV A,40H
CJNE A,22H,RETNAOZHONG
MOV A,41H
CJNE A,23H,RETNAOZHONG
MOV 32H,#0FFH
RETNAOZHONG:
RET
;-------------------------------------------------------------
;24c02读写相关子程序
RD24:
PUSH ACC ;读24C02子程序。
SETB SDA
CLR SCL
CALL START24
MOV A,#0A0H
CALL SHIFT8
CALL ACK
POP ACC
CALL SHIFT8
CALL ACK
CALL START24
MOV A,#0A1H
CALL SHIFT8
CALL ACK
SETB SDA
MOV R7,#8
CLR A
SETB SDA
RD000:
RL A
SETB SCL
MOV C,SDA
MOV ACC.0,C
CLR SCL
DJNZ R7,RD000
RET
;-------------------------------
;写入24C02程序:
WT24:
PUSH ACC
SETB SDA
CLR SCL
CALL START24
MOV A,#0A0H
CALL SHIFT8
CALL ACK
POP ACC
CALL SHIFT8
CALL ACK
MOV A,B
CALL SHIFT8
CALL ACK
CALL STOP
CALL DELAY2
MOV 46H,#0FFH
DELAY:
CALL DELAY1
DJNZ 46H,DELAY
RET
; -------------------------------
;开始条件
START24:
CLR SDA
SETB SDA
SETB SCL
CLR SDA
CLR SCL
RET
;停止条件
STOP:
CLR SDA
SETB SCL
SETB SDA
RET
;应答信号
ACK:
SETB SCL
CLR SCL
RET
;读、写数据
SHIFT8:
MOV R7,#8
SH01:
RLC A
MOV SDA,C
SETB SCL
CLR SCL
DJNZ R7,SH01
RET
DELAY2:
NOP
NOP
NOP
NOP
RET
DELAY1:
MOV 45H,#01H
C_DELAY:
MOV 44H,#0FFH
DJNZ 44H,$
DJNZ 45H,C_DELAY
RET
END ;程序结束
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -