📄 clock.asm
字号:
; 电子日历时钟.asm
; (Electronic Calendar and Clock)
; Reference for Grade 2005, s.c.u.t.
; Author: YUJIAN.XU
; Revision: version 2.0 2007/12/01
; Update : 2007/12/10
; Limitations:None
; 开关Key0(for shift/adjust即调整/时间,日期显示模式/秒表控制键)connected to INT0
; 开关Key1(for un-flash/flash即功能选择键) connected to INT1
; 开关Key2:休眠唤醒键 connected to P2.6
; 开关Key3:闹钟开关键 connected to P2.7
; 开关Key4: 系统复位键,所有数值清零,初始值从07年12月01日12:00:00开始显示
;变量定义
;SLEEP_UP EQU 38H ;休眠计时器
TICK_CNT EQU 20H ;T0溢出计数器
FLASH_FLAG EQU 27H ;00h不选择修改,01h-03h分别为"DATE"的年,月,日闪烁,
;04h-06h分别为"time"的时,分,秒闪烁,07h-09h分别为"bell"的时,分,mode闪烁
;时间
SECOND_BCD EQU 21H
MINUTE_BCD EQU 22H
HOUR_BCD EQU 23H
;闹钟
A_SEC_BCD EQU 34H
A_MIN_BCD EQU 35H
A_HOUR_BCD EQU 36H
;日期
DAY_BCD EQU 24H
MONTH_BCD EQU 25H
YEAR_BCD EQU 26H
;秒表
WATCH_FLAG EQU 30H
S_PER_SEC_BCD EQU 31H ;秒表百分之一秒
S_SEC_BCD EQU 32H
MIN_BCD EQU 33H
;LED系统功能状态标记
CLOCK_LED EQU P2.0
ALARM_LED EQU P2.1
WATCH_LED EQU P2.2
DATA_LED EQU P2.3
TIME_LED EQU P2.4
;中断向量表
ORG 0000H
LJMP MAIN
ORG 0003H
LJMP ADJUST0 ;外部中断0
ORG 000BH
LJMP TIMEUP ;定时/计数器T0中断
ORG 0013H
LJMP ADJUST1 ;外部中断1
ORG 001BH
LJMP T1_INT ;定时/计数器T1中断
ORG 0030H
MAIN: NOP ;主程序
MOV SP,#60H ;设置堆栈指针
;初始化变量
MOV P2,#0FFH
;显示的时间:
MOV SECOND_BCD, #00H ; 秒BOD码
MOV MINUTE_BCD, #00H ; 分BCD码
MOV HOUR_BCD, #12H ; 时BOD码
;显示的日期:
MOV DAY_BCD, #01H ; 天BCD码
MOV MONTH_BCD,#12H ; 月BCD码
MOV YEAR_BCD, #07H ; 年BCD码
;秒表
MOV S_PER_SEC_BCD,#00H ; 百分秒
MOV S_SEC_BCD, #00H ; 秒
MOV MIN_BCD, #00H ; ;秒表清零
MOV WATCH_FLAG, #00H ; 秒表开始/停止标志
;闹钟
MOV A_SEC_BCD,#00H
MOV A_MIN_BCD,#00H
MOV A_HOUR_BCD,#00H
MOV FLASH_FLAG,#00H ;闪烁标志
MOV R7,#00H ;时间/日期转换标志
MOV TL0,#0B0H ;装T0的时间常数
MOV TH0,#3CH ;T0一次中断时间为0.05秒
MOV TL1,#0F0H ;装T1的时间常数
MOV TH1,#0D8H
; MOV SLEEP_UP,#00H
MOV TICK_CNT,#14H ;T0循环计时次数20次(F=12Mhz)
MOV TMOD,#11H ;T0初始化:方式1,计数位16位
CLR IT0
CLR IT1
SETB ET0 ;开T0中断
SETB ET1 ;开T1中断
SETB EX0 ;开外部中断0(INT0)
SETB EX1 ;开外部中断1(INT1)
SETB EA ;CPU开中断
SETB PT0 ;设置T0中断为高优先级
SETB TR0 ;T0开始计时
CLR TR1 ;T1未计时
;LOOP1:
; MOV A,SLEEP_UP
; CJNE A,#91H,LOOP2 ;一分半钟到自动进入休眠状态
; CLR EX0 ;关外部中断
; CLR EX1
; MOV P1,#0FFH
; JB ALARM_LED,SLEEP3
;LOP: LCALL ALARM
; MOV P1,#0FFH
; JB P2.6,LOP ;P2.6按键按下激活
; LCALL DMS
; JNB P2.6,LOP ;等待按键提起
; MOV P1,#0FFH
; SJMP EXIT0
;SLEEP3:
; JB P2.6,SLEEP3 ;P2.6按键按下激活
;WEAK_UP:
; LCALL DMS
; JNB P2.6,WEAK_UP ;等待按键提起
;EXIT0:
; MOV SLEEP_UP,#00H
; SETB EX0
; SETB EX1
LOOP1:
JNB P2.7,SET_ARM ;低电平表示K3键按下,开闹钟功能
JNB P2.6,SLEEP
JB ALARM_LED,LOOP2
LCALL ALARM
LOOP2:
LCALL CHECK_STADE
LCALL CHECK_INT
LCALL DISP
SJMP LOOP1
;————————————————————————————————————
;等待中断
;————————————————————————————————————
;开闹钟
SET_ARM:
LCALL DMS ;消抖动,并显示
JNB P2.7,SET_ARM ;等待按键提起
;MOV SLEEP_UP,#00H ;自动休眠器清零
CLR ALARM_LED ; 开闹钟
SJMP LOOP1
;手动进入休眠状态
SLEEP:
LCALL DMS
JNB P2.6,SLEEP ;等待按键提起
;MOV SLEEP_UP,#00H ;自动休眠器清零
;MOV P1,#0FFH
CLR EX0 ;关外部中断
CLR EX1 ;进入休眠状态,即LED不显示,外部中断按键不响应
JB ALARM_LED,SLEEP0 ;查是否开闹钟?
LOOP3:
LCALL ALARM ;查闹钟时间到?
MOV P1,#0FFH
JB P2.6,LOOP3
SLEEP3:
LCALL DMS ;消抖动,并显示
JNB P2.6,SLEEP3 ;等待按键提起
; MOV SLEEP_UP,#00H ;自动休眠器清零
SETB EX0
SETB EX1 ;开外部中断
LJMP LOOP1
SLEEP0:
JB P2.6,SLEEP0 ;再次按 K2键,则退出休眠状态
SLEEP1:
LCALL DMS ;消抖动,并显示
JNB P2.6,SLEEP1 ;等待按键提起
; MOV SLEEP_UP,#00H ;自动休眠器清零
SETB EX0 ;开外部中断
SETB EX1
LJMP LOOP1
;系统功能状态功能查询
CHECK_STADE: ;R7='00'显示时间状态LED亮
PUSH ACC
MOV A,R7
CJNE A,#00H,CHECK1
CLR TIME_LED
SETB DATA_LED
SETB WATCH_LED
SETB P2.0
SJMP CHECK_OUT
CHECK1:
CJNE A,#01H,CHECK2 ;R7='01'显示日期状态LED亮
SETB TIME_LED
CLR DATA_LED
SETB WATCH_LED
SETB P2.0
SJMP CHECK_OUT
CHECK2:
CJNE A,#02H,CHECK3 ;R7='02'显示秒表状态LED亮
SETB TIME_LED
SETB DATA_LED
CLR WATCH_LED
SETB P2.0
SJMP CHECK_OUT
CHECK3: ;R7='03'显示闹钟设定时间状态LED亮
SETB TIME_LED
SETB DATA_LED
SETB WATCH_LED
CLR P2.0
CHECK_OUT:
POP ACC
RET
;闹钟查询
ALARM:
PUSH ACC
MOV A,23H
CJNE A,36H,DONT
MOV A,22H
CJNE A,35H,DONT
MOV A,21H
CJNE A,34H,DONT
ALARM1:
LCALL DISP
CPL P2.5 ;开/关蜂鸣器
LCALL DMS ;延时响应
JB P2.7,ANEXT ;P2.7按下关闹铃
AL0:
LCALL DMS
JNB P2.7,AL0
MOV P1,#0FFH
LCALL DISP
SETB P2.1 ;关闹钟标记位
SETB P2.5
SETB P2.6
SJMP DONT
ANEXT: SJMP ALARM1
DONT:
POP ACC
RET
;整点报时
CHECK_INT:
MOV A,22H
CJNE A,#00H,C_OUT
MOV A,21H
CJNE A,#00H,C_OUT
CPL P2.5
LCALL DMS
SETB P2.5
C_OUT:NOP
RET
;——————————————————————————————————
; 定时器1中断;用于秒表
;——————————————————————————————————
T1_INT: MOV TL1,#0F0H ;重载T1,0.01s
MOV TH1,#0D8H ;
MOV A,S_PER_SEC_BCD ; 取变量S_PER_SEC_BCD的值
CJNE A,#99H,SIN3 ; 到达100 S_PER_SEC ?
SJMP SIN4
SIN3: LJMP S_PER_SEC_INC
SIN4: MOV S_PER_SEC_BCD,#00H ; 当到达100次后,重新赋0值
MOV A,S_SEC_BCD
CJNE A,#59H,SIN5
SJMP SIN6
SIN5: LJMP S_SEC_INC
SIN6: MOV S_SEC_BCD,#00H
MOV A, MIN_BCD
CJNE A,#59H,SIN7
SJMP SIN8
SIN7: LJMP MIN_INC
SIN8: MOV MIN_BCD,#00H
SJMP T1_RET
MIN_INC: ;加1m
MOV A,MIN_BCD
ADD A,#01H
DA A
MOV MIN_BCD,A
SJMP T1_RET
S_SEC_INC: ;加1s
MOV A,S_SEC_BCD
ADD A,#01H
DA A
MOV S_SEC_BCD,A
SJMP T1_RET
S_PER_SEC_INC: ; 加0.01s
MOV A,S_PER_SEC_BCD
ADD A,#01H
DA A
MOV S_PER_SEC_BCD,A
T1_RET: RETI
; ————————————————————————————————————
; sub:Author: BY YUJIAN.XU T0中断程序
;—————————————————————————————————————
TIMEUP: MOV TL0,#0B0H ;重装T0的时间常数
MOV TH0,#3CH
DJNZ 20H,INTER1 ;循环20次(是否达到1秒)?
;MOV A,SLEEP_UP
;CJNE A,#91H,SLADD ;查询休眠时间到?
SJMP INTER2
;SLADD:MOV A,SLEEP_UP ;取自动休眠计时器秒的BCD码
; ADD A,#01H ;加一秒
; DA A ;BCD码调整
; MOV SLEEP_UP ,A
; SJMP INTER2
INTER1: LJMP LAST
INTER2: MOV A,21H ;取秒的BCD码
CJNE A,#59H,INTER3 ;是否达到59秒,否则转秒加一
SJMP INTER4
INTER3: LJMP SADD
INTER4: MOV 21H,#00H ;存第一秒数值
MOV A,22H ;取分的BCD码
CJNE A,#59H,INTER5 ;是否达到59分,否则转分加一
SJMP INTER6
INTER5: LJMP MADD
INTER6: MOV 22H,#00H ;存第一分数值
MOV A,23H ;取小时的BCD码
CJNE A,#23H,HADD ;是否达到23时,否则转小时加一
MOV 23H,#00H ;存第一小时数值
MOV A,25H ;取月的BCD码
CJNE A,#02H,NOTFEB ;是否2月,否则转大小月判断
ISFEB: NOP
ACALL DIVBCD ;调用平年闰年判断程序
MOV A,R3 ;程序参数传递(R3)->(A)
CJNE A,#00H,PING ;"00H"说明是闰年
RUN: MOV A,24H ;取(二月)日的BCD码
CJNE A,#29H,DDADD ;是否为29号,否则转日加一
MOV 24H,#01H ;存第一天数值(1号)
MOV 25H,#03H ;月份改为3月
SJMP CONT
PING: MOV A,24H ;取(二月)日的BCD码
CJNE A,#28H,DDADD ;是否为28号,否则转日加一
MOV 24H,#01H ;存第一天数值(1号)
MOV 25H,#03H ;月份改为3月
SJMP CONT
NOTFEB: NOP ;二月之外的其他月份处理
CJNE A,#04H,YUE1 ;是否为4月?
AJMP T12
YUE1: CJNE A,#06H,YUE2 ;是否为6月?
AJMP T12
YUE2: CJNE A,#09H,YUE3 ;是否为9月?
AJMP T12
YUE3: CJNE A,#11H,T11 ;是否为11月?
AJMP T12
T11: MOV A,24H ;取(大月)日的BCD码
CJNE A,#31H,DDADD ;是否为31号,否则转日加一
AJMP T30
T12: MOV A,24H ;取(小月)日的BCD码
CJNE A,#30H,DDADD ;是否为30号,否则转日加一
T30: MOV 24H,#01H ;存第一天数值(1号)
MOV A,25H ;取月的BCD码
CJNE A,#12H,MMADD ;是否为12月,否则转月加一
MOV 25H,#01H ;存第一月数值(1月)
MOV A,26H ;取年的BCD码
CJNE A,#99H,YYADD ;是否为99年,否则转年加一
MOV 26H,#00H ;存第一年数值(00年)
SJMP CONT
YYADD: MOV A,26H ;取年的BCD码
ADD A,#01H ;年数值加一
DA A ;BCD码调整
MOV 26H,A ;存年的数值
SJMP CONT
MMADD: MOV A,25H ;取月的BCD码
ADD A,#01H ;月数值加一
DA A ;BCD码调整
MOV 25H,A ;存月的数值
SJMP CONT
DDADD: MOV A,24H ;取日的BCD码
ADD A,#01H ;日数值加一
DA A ;BCD码调整
MOV 24H,A ;存日的数值
SJMP CONT
HADD: MOV A,23H ;取时的BCD码
ADD A,#01H ;时数值加一
DA A ;BCD码调整
MOV 23H,A ;存时的数值
SJMP CONT
MADD: MOV A,22H ;取分的BCD码
ADD A,#01H ;分数值加一
DA A ;BCD调整
MOV 22H,A ;存分的数值
SJMP CONT
SADD: MOV A,21H ;取秒的BCD码
ADD A,#01H ;秒加一
DA A ;BCD码调整
MOV 21H,A ;存秒的数值
CONT: MOV 20H,#14H ;重置T0计时循环次数20次(新的一秒开始)
LAST: RETI
;————————————————————————————————————
;sub:Author: By YUJIAN.XU 数码管 显示子程序
;————————————————————————————————————
DISP: MOV DPTR,#TABLE ;取显示编码表头地址
MOV A,R7 ;取时间/日期转换显示标志
CJNE A,#00H,DATE ;"00H"为显示时间
TIME: MOV R0,#21H ;取秒地址
SJMP TSAVE
DATE:
CJNE A,#01H,WATCH
MOV R0,#24H ;"FFH"为显示日期,取日地址
SJMP TSAVE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -