📄 12864.asm
字号:
;*********************************************************************************
X EQU 26H ;LCD 地址变量
;**************变量的定义*****************
RS BIT P2.0 ;LCD数据/命令选择端(H/L)
RW BIT P2.1 ;LCD读/写选择端(H/L)
EP BIT P2.2 ;LCD使能控制
PSB EQU P2.3
RST EQU P2.5
PRE BIT P1.4 ;调整键(K1)
ADJ BIT P1.5 ;调整键(K2)
COMDAT EQU P0
LED EQU P0.3
YEAR DATA 18H ;年,月,日变量
MONTH DATA 19H
DATE DATA 1AH
WEEK DATA 1BH
HOUR DATA 1CH ;时,分,秒,百分之一秒变量
MIN DATA 1DH
SEC DATA 1EH
SEC100 DATA 1FH
STATE DATA 23H
LEAP BIT STATE.1 ;是否闰年标志1--闰年,0--平年
KEY_S DATA 24H ;当前扫描键值
KEY_V DATA 25H ;上次扫描键值
DIS_BUF_U0 DATA 26H ;LCD第一排显示缓冲区
DIS_BUF_U1 DATA 27H
DIS_BUF_U2 DATA 28H
DIS_BUF_U3 DATA 29H
DIS_BUF_U4 DATA 2AH
DIS_BUF_U5 DATA 2BH
DIS_BUF_U6 DATA 2CH
DIS_BUF_U7 DATA 2DH
DIS_BUF_U8 DATA 2EH
DIS_BUF_U9 DATA 2FH
DIS_BUF_U10 DATA 30H
DIS_BUF_U11 DATA 31H
DIS_BUF_U12 DATA 32H
DIS_BUF_U13 DATA 33H
DIS_BUF_U14 DATA 34H
DIS_BUF_U15 DATA 35H
DIS_BUF_L0 DATA 36H ;LCD第三排显示缓冲区
DIS_BUF_L1 DATA 37H
DIS_BUF_L2 DATA 38H
DIS_BUF_L3 DATA 39H
DIS_BUF_L4 DATA 3AH
DIS_BUF_L5 DATA 3BH
DIS_BUF_L6 DATA 3CH
DIS_BUF_L7 DATA 3DH
DIS_BUF_L8 DATA 3EH
DIS_BUF_L9 DATA 3FH
DIS_BUF_L10 DATA 40H
DIS_BUF_L11 DATA 41H
DIS_BUF_L12 DATA 42H
DIS_BUF_L13 DATA 43H
DIS_BUF_L14 DATA 44H
DIS_BUF_L15 DATA 45H
FLAG DATA 46H ;1-年,2-月,3-日,4-时,5-分,6-秒,7-退出调整。
DIS_H DATA 47H
DIS_M DATA 48H
DIS_S DATA 49H
;******************初始化***********************
ORG 0000H
LJMP START
ORG 000BH
LJMP TIMER0
ORG 0100H
START: MOV SP,#60H
MOV R0,#18H
MOV A,#00H
CLR LED
MEM_INI: MOV @R0,A
INC R0
CJNE R0,#5FH,MEM_INI
LCALL DELAY_5ms ;初始化LCD
MOV R0,#38H ;设置LCD为16X2显示,5X7点阵,八位数据接口
LCALL LCD_WCMD
LCALL DELAY_5ms
MOV R0,#0CH ;设置LCD开显示及光标形式(光标不闪烁,不显?-")
LCALL LCD_WCMD
LCALL DELAY_5ms
MOV R0,#06H ;LCD显示光标移动设置(光标地址指针加1,整屏显示不移动)
LCALL LCD_WCMD
LCALL DELAY_5ms
MOV R0,#01H ;清除LCD的显示内容
LCALL LCD_WCMD
LCALL DELAY_5ms
MOV YEAR,#00 ;置年初值
MOV MONTH,#01 ;置月初值
MOV DATE,#01 ;置日初值
MOV DIS_H,#12
MOV HOUR,#12
LCALL WEEK_PRO
LCALL UPDATE_BUF
LCALL DISPLAY_PRO ;屏显初始化
;*********************主程序*********************
MAIN: MOV IE,#8AH ;CPU开中断,Timer0,Timer1开中断
MOV TMOD,#01H ;Timer0,Timer1工作于模式1, 16位定时方式
MOV TH0,#3CH ;Timer0置50ms定时初值
MOV TL0,#0B0H
SETB TR0 ;Timer0启动
MOV KEY_V,#03H
MAIN_1: LCALL KEY_SCAN
MOV A,KEY_S
XRL A,KEY_V
JZ MAIN_1
LCALL DELAY_5ms
LCALL DELAY_5ms
LCALL KEY_SCAN
MOV A,KEY_S
XRL A,KEY_V
JZ MAIN_1
MOV KEY_V,KEY_S
MOV A,KEY_V
XRL A,#01H
JNZ MAIN_2
CLR TR0 ;进入调整状态,禁止Timer0
MOV IE,#00H ;CPU禁止中断
LCALL KEY_PRE_PRO ;PRE按键按下,调用PRE按键处理程序
SJMP MAIN_1
MAIN_2: MOV A,KEY_V
XRL A,#02H
JNZ MAIN_1
LCALL KEY_ADJ_PRO ;ADJ按键按下,调用PRE按键处理程序
SJMP MAIN_1
;*******************按键扫描程序******************
KEY_SCAN: CLR A
MOV P3,#0FFH
MOV C,PRE
MOV ACC.1,C
MOV C,ADJ
MOV ACC.0,C
MOV KEY_S,A ;本次扫描键值存入KEY_S
RET
;**************PRE按键处理程序*******************
KEY_PRE_PRO: INC FLAG
MOV R4,FLAG
MOV R0,#0EH
LCALL LCD_WCMD ;显示光标"_",整个光标不闪烁
KEY_PRE_4: CJNE R4,#1,KEY_PRE_5
MOV R0,#02H
LCALL LCD_POS ;光标置年调整位置
JMP KEY_PRE_E
KEY_PRE_5: CJNE R4,#2, KEY_PRE_6
MOV R0,#04H
LCALL LCD_POS ;光标置月调整位置
JMP KEY_PRE_E
KEY_PRE_6: CJNE R4,#3,KEY_PRE_7
MOV R0,#06H
LCALL LCD_POS ;光标置日调整位置
JMP KEY_PRE_E
KEY_PRE_7: CJNE R4,#4,KEY_PRE_8
MOV R0,#14H
LCALL LCD_POS ;光标置时调整位置
JMP KEY_PRE_E
KEY_PRE_8: CJNE R4,#5,KEY_PRE_9
MOV R0,#15H
LCALL LCD_POS ;光标置分调整位置
JMP KEY_PRE_E
KEY_PRE_9: CJNE R4,#6,KEY_PRE_10
MOV R0,#17H
LCALL LCD_POS ;光标置秒调整位置
JMP KEY_PRE_E
KEY_PRE_10:MOV FLAG,#0 ;FLAG到7,就清零
MOV R0,#0CH
LCALL LCD_WCMD ;设置LCD开显示及光标不闪烁,不显示"-"
; MOV R0,#01H
; LCALL LCD_WCMD ;清除LCD的显示内容
MOV IE,#8AH ;CPU开中断,TIMER0,TIMER1开中断
SETB TR0 ;启动TIMER0
KEY_PRE_E: RET
;**************ADJ按键处理程序*******************
KEY_ADJ_PRO:MOV R0,#0CH
LCALL LCD_WCMD ;设置LCD开显示及光标不闪烁,不显示"-"
MOV R5,FLAG
KEY_ADJ_4: CJNE R5,#1,KEY_ADJ_5 ;FLAG=5,调整年
KEY_ADJ_40:INC YEAR
MOV A,YEAR
CJNE A,#100,KEY_ADJ_4_1
MOV YEAR,#0
KEY_ADJ_4_1: LCALL WEEK_PRO
LCALL UPDATE_BUF
LCALL DISPLAY_PRO
MOV R0,#05H
LCALL LCD_POS
LCALL DELAY_200ms
JNB ADJ,KEY_ADJ_40
JMP KEY_ADJ_E
KEY_ADJ_5: CJNE R5,#2,KEY_ADJ_6 ;FLAG=6,调整月
KEY_ADJ_50:INC MONTH
MOV A,MONTH
CJNE A,#13,KEY_ADJ_5_1
MOV MONTH,#1
KEY_ADJ_5_1: LCALL WEEK_PRO
LCALL UPDATE_BUF
LCALL DISPLAY_PRO
MOV R0,#08H
LCALL LCD_POS
LCALL DELAY_200ms
JNB ADJ,KEY_ADJ_50
JMP KEY_ADJ_E
KEY_ADJ_6: CJNE R5,#3,KEY_ADJ_7 ;FLAG=7,调整日
KEY_ADJ_60:INC DATE
MOV A,MONTH
XRL A,#2
JNZ KEY_ADJ_6_2 ;不是二月跳转
MOV A,DATE ;
MOV C,LEAP ;判断是否闰年
JC KEY_ADJ_6_1
XRL A,#29 ;平年二月日期28天
JNZ KEY_ADJ_6_5
JMP KEY_ADJ_6_4
KEY_ADJ_6_1: XRL A,#30 ;闰年二月日期29天
JNZ KEY_ADJ_6_5
JMP KEY_ADJ_6_4 ;跳转到月处理
KEY_ADJ_6_2: MOV A,MONTH
XRL A,#4
JZ KEY_ADJ_6_3
MOV A,MONTH
XRL A,#6
JZ KEY_ADJ_6_3
MOV A,MONTH
XRL A,#9
JZ KEY_ADJ_6_3
MOV A,MONTH
XRL A,#11
JZ KEY_ADJ_6_3
MOV A,DATE
XRL A,#32 ;大月日期31天
JNZ KEY_ADJ_6_5
JMP KEY_ADJ_6_4
KEY_ADJ_6_3: MOV A,DATE
XRL A,#31 ;小月日期30天
JNZ KEY_ADJ_6_5
KEY_ADJ_6_4: MOV DATE,#1
KEY_ADJ_6_5: LCALL WEEK_PRO
LCALL UPDATE_BUF
LCALL DISPLAY_PRO
MOV R0,#0BH
LCALL LCD_POS
LCALL DELAY_200ms
JNB ADJ,KEY_ADJ_60
JMP KEY_ADJ_E
KEY_ADJ_7: CJNE R5,#4,KEY_ADJ_8 ;FLAG=8,调整时
KEY_ADJ_70:INC HOUR
MOV A,HOUR
CJNE A,#24,KEY_ADJ_7_1
MOV HOUR,#0
KEY_ADJ_7_1: MOV DIS_H,HOUR
LCALL UPDATE_BUF
LCALL DISPLAY_PRO
MOV R0,#49H
LCALL LCD_POS
LCALL DELAY_200ms
JNB ADJ,KEY_ADJ_70
JMP KEY_ADJ_E
KEY_ADJ_8: CJNE R5,#5,KEY_ADJ_9 ;FLAG=9,调整分
KEY_ADJ_80: INC MIN
MOV A,MIN
CJNE A,#60,KEY_ADJ_8_1
MOV MIN,#0
KEY_ADJ_8_1: MOV DIS_M,MIN
LCALL UPDATE_BUF
LCALL DISPLAY_PRO
MOV R0,#4CH
LCALL LCD_POS
LCALL DELAY_200ms
JNB ADJ,KEY_ADJ_80
JMP KEY_ADJ_E
KEY_ADJ_9: CJNE R5,#6,KEY_ADJ_E ;FLAG=10,调整秒
KEY_ADJ_90:INC SEC
MOV A,SEC
CJNE A,#60,KEY_ADJ_9_1
MOV SEC,#0
KEY_ADJ_9_1: MOV DIS_S,SEC
LCALL UPDATE_BUF
LCALL DISPLAY_PRO
MOV R0,#4FH
LCALL LCD_POS
LCALL DELAY_200ms
JNB ADJ,KEY_ADJ_90
KEY_ADJ_E: RET
;***************Timer0定时中断程序*****************
TIMER0: MOV TH0,#3CH
MOV TL0,#0B0H
INC SEC100
MOV A,SEC100
CJNE A,#20,TIMER0_E
MOV SEC100,#0
LCALL TIME_PRO
TIMER0_2: MOV DIS_H,HOUR
MOV DIS_M,MIN
MOV DIS_S,SEC
LCALL UPDATE_BUF
LCALL DISPLAY_PRO
TIMER0_E: RETI
;**************时间日期处理函数******************
TIME_PRO: INC SEC ;秒处理
MOV A,SEC
CJNE A,#60,TIME_PRO_e
MOV SEC,#0
INC MIN ;分处理
MOV A,MIN
CJNE A,#60,TIME_PRO_e
MOV MIN,#0
INC HOUR ;时处理
MOV A,HOUR
CJNE A,#24,TIME_PRO_e
MOV HOUR,#0
INC DATE ;日处理(日处理要考虑是否闰年,大月,小月)
MOV A,MONTH
XRL A,#2
JNZ TIME_PRO_D2 ;不是二月,转TIME_PRO_D2
MOV A,DATE ;
MOV C,LEAP ;判断是否闰年
JC TIME_PRO_D1
XRL A,#29 ;平年二月日期28天
JNZ TIME_PRO_W
SJMP TIME_PRO_M ;跳转到月处理
TIME_PRO_D1:XRL A,#30 ;闰年二月日期29天
JNZ TIME_PRO_W
SJMP TIME_PRO_M ;跳转到月处理
TIME_PRO_D2:MOV A,MONTH
XRL A,#4
JZ TIME_PRO_D3
MOV A,MONTH
XRL A,#6
JZ TIME_PRO_D3
MOV A,MONTH
XRL A,#9
JZ TIME_PRO_D3
MOV A,MONTH
XRL A,#11
JZ TIME_PRO_D3
MOV A,DATE
XRL A,#32 ;大月日期31天
JNZ TIME_PRO_W
SJMP TIME_PRO_M ;跳转到月处理
TIME_PRO_D3:MOV A,DATE
XRL A,#31 ;小月日期30天
JNZ TIME_PRO_W
TIME_PRO_M:MOV DATE,#1
INC MONTH ;月处理
MOV A,MONTH
CJNE A,#13,TIME_PRO_W
MOV MONTH,#1
INC YEAR ;年处理
MOV A,YEAR
CJNE A,#100,TIME_PRO_W
MOV YEAR,#0
TIME_PRO_W:LCALL WEEK_PRO ;星期处理
TIME_PRO_E:RET
;**********星期自动运算函数*********************
;星期运算常数W(5或6)
;闰年的数目L(0--99年:L=YEAR/4 整除)
;年数YEAR
;月参变数MONTH_TAB(0,3,3,6,1,4,6,2,5,0,3,5)
;日期DATE
;星期数=(W+L+YEAR+MONTH_TAB+DATE)%7 (求余)
WEEK_PRO: MOV A,MONTH ;确定星期运算常数W
XRL A,#1
JZ WEEK_PRO_1
MOV A,MONTH
XRL A,#2
JZ WEEK_PRO_1
SJMP WEEK_PRO_2
WEEK_PRO_1:LCALL LEAP_PRO
MOV C,LEAP
JNC WEEK_PRO_2
MOV R3,#5
SJMP WEEK_PRO_3
WEEK_PRO_2:MOV R3,#6
WEEK_PRO_3:MOV A,YEAR ;计算闰年的数目L
MOV B,#4
DIV AB
ADD A,R3 ;W+L
MOV R3,A
MOV A,YEAR
ADD A,R3 ;(W+L)+YEAR
MOV R3,A
MOV DPTR,#MONTH_TAB
MOV A,MONTH
MOVC A,@A+DPTR
ADD A,R3 ;(W+L+YEAR)+MONTH_TAB
MOV R3,A
MOV A,DATE
ADD A,R3 ;(W+L+YEAR+MONTH_TAB+DATE)
MOV B,#7
DIV AB ;余数即为星期数
MOV WEEK,B
RET
;**********闰年的判断函数*********************
;闰年的条件:年(YEAR)能被4整除、但不能被100整除;或者被400整除。
;如果我们只考虑(00--99),则只需考虑年(YEAR)能被4整除即可。
LEAP_PRO: MOV A,YEAR
MOV B,#4
DIV AB
MOV A,B
JZ LEAP_PRO_1 ;能被4整除
CLR LEAP ;平年,清零LEAP
LJMP LEAP_PRO_E
LEAP_PRO_1:SETB LEAP ;闰年,置位LEAP
LEAP_PRO_E:RET
;**********更新显示缓冲区********************
;入口R1,
UPDATE_BUF:MOV DIS_BUF_U0,#20H;空格
MOV DIS_BUF_U1,#20H;空格
MOV DIS_BUF_U2,#32H ;"2"
MOV DIS_BUF_U3,#30H ;"0"
MOV A,YEAR ;更新年数据
MOV B,#10
DIV AB
ADD A,#48 ;二进制转换为ASCMA码
MOV DIS_BUF_U4,A
MOV A,B
ADD A,#48
MOV DIS_BUF_U5,A
MOV DIS_BUF_U6,#0c4H ;"-"
MOV DIS_BUF_U7,#0eaH;"-"
MOV A,MONTH ;更新月数据
MOV B,#10
DIV AB
ADD A,#48
MOV DIS_BUF_U8,A
MOV A,B
ADD A,#48
MOV DIS_BUF_U9,A
MOV DIS_BUF_U10,#0d4H ;"-"
MOV DIS_BUF_U11,#0c2H
MOV A,DATE ;更新日数据
MOV B,#10
DIV AB
ADD A,#48
MOV DIS_BUF_U12,A
MOV A,B
ADD A,#48
MOV DIS_BUF_U13,A
MOV DIS_BUF_U14,#0c8H;空格
MOV DIS_BUF_U15,#0d5H;空格
MOV DIS_BUF_L0,#0d0h
MOV DIS_BUF_L1,#0c7h
MOV DIS_BUF_L2,#0c6h
MOV DIS_BUF_L3,#0dah
MOV A,week
CJNE A,#1,week1 ;1显示星期一
MOV DIS_BUF_L4,#0d2h
MOV DIS_BUF_L5,#0bbh
SJMP UPDATE_BUF_2
week1:CJNE A,#2,week2 ;2显示星期二
MOV DIS_BUF_L4,#0b6h
MOV DIS_BUF_L5,#0feh
SJMP UPDATE_BUF_2
week2:CJNE A,#3,week3 ;3显示星期三
MOV DIS_BUF_L4,#0c8h
MOV DIS_BUF_L5,#0fdh
SJMP UPDATE_BUF_2
week3:CJNE A,#4,week4 ;4显示星期四
MOV DIS_BUF_L4,#0cbh
MOV DIS_BUF_L5,#0c4h
SJMP UPDATE_BUF_2
week4:CJNE A,#5,week5 ;5显示星期五
MOV DIS_BUF_L4,#0ceh
MOV DIS_BUF_L5,#0e5h
SJMP UPDATE_BUF_2
week5:CJNE A,#6,week6 ;6显示星期六
MOV DIS_BUF_L4,#0c1h
MOV DIS_BUF_L5,#0f9h
SJMP UPDATE_BUF_2
week6:MOV DIS_BUF_L4,#0c8h ;7显示星期日
MOV DIS_BUF_L5,#0d5h
MOV DIS_BUF_L6,#' ' ;空格
UPDATE_BUF_2:MOV DIS_BUF_L7,#' ' ;空格
MOV A,DIS_H
MOV B,#10
DIV AB
ADD A,#48
MOV DIS_BUF_L8,A
MOV A,B
ADD A,#48
MOV DIS_BUF_L9,A
MOV DIS_BUF_L10,#3AH;":"
MOV A,DIS_M
MOV B,#10
DIV AB
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -