📄 程序.txt
字号:
CDAY DATA 37H
YEAR2 DATA 38H
YEAR1 DATA 39H
MONTH DATA 3AH
DAY DATA 3BH
WEEK DATA 3CH
HOUR DATA 3DH
MINUTE DATA 3EH
SECOND DATA 3FH
TIME1 DATA 40H
TIME01 DATA 60H
TIME32 DATA 5FH
TIME032 DATA 7FH
DISPB1 BIT 10H
DISPB2 BIT 11H
BTIME1 DATA 2AH
BTIME2 DATA 2BH
KEYSTU DATA 27H
PORTDR DATA 28H
SDI BIT P1.2
SCLK BIT P3.4
PCLK BIT P3.5
DISPLAY1 DATA 24H
DISPLAY2 DATA 25H
DISPBUF DATA 2FH
STORE DATA 33H ;STORE+1为34H,STORE+2为35H,STORE+3为36H。
MTIME DATA 2CH ;作为查询左右键移位0.5秒的计数器。
UP DATA 26H
DOWN DATA 23H
FLASH BIT 13H ;用于调整时数码管亮-暗的标志
FLASHPLAY DATA 21H ;用于调整时对应的数码管的代
DISCOUNT DATA 29H
FCOUNT DATA 2DH ;作为调整时秒闪动时的计数器
LIGHT DATA 2EH
PORTA EQU 9000H ;8255A口地址
PORTB EQU 9100H ;8255B口地址
PORTC EQU 9200H ;8255C口地址
PORTS EQU 9300H ;8255控制/状态口地址
PORTD EQU 8800H ;U105(八上升沿D型触发器74HC273)地址
;主程序开始
ORG 0000H
LJMP MAIN
ORG 002BH
LJMP CTC2 ;定时/计数器T2中断服务程序入口地址
ORG 0050H
;-----主程序开始-----
PROC MAIN
MAIN:
MOV SP, #0CFH ;将0D0H-0FFH,共计48字节作为堆栈区
MOV DPTR, #8000H ;关闭蜂鸣器
MOV A, #0FFH
MOVX @DPTR, A
MOV R0, #01H ;---复位后,将01H-0FF内部RAM单元清0。
LOOP1:
MOV @R0, #0
INC R0
CJNE R0,#0, LOOP1
;----初始化定时器T2
MOV TH2, #0DCH
MOV TL2, #00H ;初值0DC00送定时器T2
MOV RCAP2H, #0DCH
MOV RCAP2L, #00H ;初始化重装初值
MOV T2CON, #00000100B ;初始化T2工作方式(自动重装初值、定时)
;并启动了T2
;-----初始化中断控制器
ORL IE, #10100000B
;SETB ET2 ;允许定时器T2中断
;SETB EA ;开中断
MOV YEAR2,#14H
MOV YEAR1,#06H
MOV MONTH,#7
MOV DAY,#12
MOV WEEK,#3H
MOV HOUR,#9
MOV MINUTE,#30
MOV SECOND,#45
CLR F0 ;作为闰年的标志
MOV R7,#40H
MOV R0,#TIME1
LAP658: MOV @R0,#88
INC R0
DJNZ R7,LAP658
MOV BTIME2, #100 ;T2每10ms中断一次,则BTIME回零时间为100*10ms
MOV BTIME1,#3 ;键盘每30ms检测一次
WAIT:
JNB DISPB1, LOOP001
CLR DISPB1
LCALL KEYCHK
LOOP001: JNB DISPB2,WAIT
CLR DISPB2
MOV A,20H
JNZ WAIT
JB 15H,WAIT0
MOV DISPLAY2,HOUR
MOV DISPLAY1,MINUTE
LCALL DISPLAY
LCALL S_DISP
SJMP WAIT
WAIT0: MOV DISPLAY2,MINUTE
MOV DISPLAY1,SECOND
LCALL DISPLAY
LCALL S_DISP
SJMP WAIT
END
PROC CTC2
CTC2:
PUSH PSW
PUSH ACC
PUSH DPH
PUSH DPL
SETB RS1 ;工作于3区
SETB RS0
JNB 17H,NEXT7
MOV A,20H
JNZ NEXT8
DEC R4
DJNZ R4,NEXT7
MOV R4,#100
DJNZ R5,NEXT7
NEXT8: CLR 17H
MOV DPTR,#8000H
MOV A,#0FFH
MOVX @DPTR,A
NEXT7: DJNZ BTIME1, LOOKLAP ;判断定时检测键盘的时间是否到
MOV BTIME1,#3
SETB DISPB1
LOOKLAP: DJNZ BTIME2, NEXT003 ;判断秒是否到
;溢出次数已经回到0,重新初始化溢出次数
MOV BTIME2, #100
SETB DISPB2
INC SECOND ;秒计数单元+1
MOV A, SECOND
CJNE A, #60, NEXT1
NEXT1:
JC NEXT003
;秒大于60,从0开始计数,且分计数单元加1
MOV SECOND, #0
INC MINUTE
MOV A,MINUTE ;定时处理程序
CJNE A,#60,GOON0
MOV R2,#0
MOV R3,HOUR
INC R3
SJMP GOON1
GOON0: MOV R2,MINUTE
MOV R3,HOUR
GOON1: MOV R0,#TIME1
MOV R7,#32
GOON3: MOV B,R3
MOV A,@R0
CJNE A,B,GOON2
MOV A,R0
ADD A,#32
MOV R1,A
MOV A,@R1
MOV B,R2
CJNE A,B,GOON2
MOV DPTR,#8000H
MOV A,#7FH
MOVX @DPTR,A
MOV R4,#100
MOV R5,#10
SETB 17H
SJMP GOON4
GOON2: INC R0
DJNZ R7,GOON3
SJMP GOON4
NEXT003:LJMP NEXT2 ;接力
GOON4:
MOV A, MINUTE
CJNE A, #60, NEXT21
NEXT21:
JC NEXT002 ;分小于60
MOV MINUTE, #0
INC HOUR
MOV A,HOUR
CJNE A,#24,NEXT22
NEXT22:JC NEXT002
MOV HOUR,#0
INC WEEK
MOV A,WEEK
CJNE A,#8H,GOON11
SJMP GOON12
GOON11:JC NEXT01
GOON12:MOV WEEK,#1
NEXT01: INC DAY
MOV A,MONTH
DEC A
JB F0,NEXT4 ;此为判别当月的天数
MOV DPTR,#TAB1 ;TAB1作为非闰年,TAB2作为闰年表
SJMP NEXT5
NEXT4:MOV DPTR,#TAB2
NEXT5:MOVC A,@A+DPTR
MOV CDAY,A
MOV A,DAY
CJNE A,CDAY,NEXT23
SJMP NEXT002
NEXT23:JC NEXT002
MOV DAY,#1
INC MONTH
SJMP LAP011
NEXT002:SJMP NEXT2
LAP011: MOV A,MONTH
CJNE A,#13,NEXT24
NEXT24:JC NEXT2
MOV MONTH,#1
INC YEAR1 ;年加1
MOV A,#YEAR1
CJNE A,#100,NEXT25
NEXT25:JC NEXT27
MOV YEAR1,#0
INC YEAR2
MOV A,YEAR2
CJNE A,#100,NEXT26
NEXT26:JC NEXT27
MOV YEAR2,#0
NEXT27:MOV A,YEAR1 ;对是否闰年进行判断
JNZ NEXT28
MOV A,YEAR2
RRC A
JC NEXT6
RRC A
JC NEXT6
NEXT28: MOV A,YEAR1
RRC A
JC NEXT6
RRC A
JC NEXT6
SETB F0
SJMP NEXT2
NEXT6:CLR F0
NEXT2:CLR TF2
POP DPL
POP DPH
POP ACC
POP PSW
RETI
END
PROC DISPLAY
DISPLAY:
;秒单元计数器笔段码送显示缓冲区
PUSH PSW
CLR RS1
CLR RS0
MOV A, DISPLAY1
MOV B, #10
DIV AB ;转换为BCD码
;十位在A中,个位在B中
MOV DPTR, #LEDTAB ;0-F字模表首地址送DPTR
MOV R0, #DISPBUF+2
MOVC A, @A+DPTR ;查表取笔段码
MOV @R0, A ;秒高位笔段码送显示缓冲区
INC R0 ;指向缓冲区最低位
MOV A, B ;取个位码
MOVC A, @A+DPTR ;查表取笔段码
MOV @R0, A ;秒低位笔段码送显示缓冲区
;分单元计数器笔段码送显示缓冲区
MOV A, DISPLAY2
MOV B, #10
DIV AB ;转换为BCD码
;十位在A中,个位在B中
MOV DPTR, #LEDTAB ;0-F字模表首地址送DPTR
MOV R0, #DISPBUF
MOVC A, @A+DPTR ;查表取笔段码
MOV @R0, A ;分高位笔段码送显示缓冲区
INC R0 ;指向缓冲区最低位
MOV A, B ;取个位码
MOVC A, @A+DPTR ;查表取笔段码
MOV @R0, A ;分低位笔段码送显示缓冲区
POP PSW
RET
END
PROC S_DISP ;串行输出子程序
S_DISP:
PUSH PSW
CLR RS1
CLR RS0
MOV R0, #DISPBUF ;显示缓冲区首地址送R0
MOV R7, #4
LOOP2:
MOV A, @R0
MOV R6, #8
LOOP1:
CLR P3.4
RLC A
MOV P1.2, C ;串行数据送P1.2引脚
NOP
SETB P3.4 ;锁存串行输入数据
DJNZ R6, LOOP1
;取下一显示码
INC R0
DJNZ R7, LOOP2
;4位笔段码已全部移到串入并出芯片中
CLR P3.5
NOP ;延迟一个机器周期
SETB P3.5
POP PSW
RET
END
PROC KEYCHK ;键盘检测
KEYCHK:
;---键盘检测-----------
MOV DPTR, #PORTD ;U105口地址送DPTR
MOV A, PORTDR ;读U105口在内存中的映象地址
ANL A, #0E0H ;输出全为低电平的扫描信号
MOVX @DPTR, A ;数据送U105输出口,将PD4~PD0置为低电平
MOV DPTR, #PORTB ;8255(U107)B口地址送DPTR
MOVX A, @DPTR ;读出B口
ANL A, #0FH ;屏蔽高4位
CJNE A, #0FH, NEXT1
;等于0F,说明没有按键被按下
SETB C ;将C标志置1
SJMP NEXT2
NEXT1:
CLR C ;C标志清0
NEXT2:
MOV A, KEYSTU
RLC A ;左移一位,记录最新的按键状态
ANL A, #07H ;保留按键状态
MOV KEYSTU, A ;保存按键状态
;判别按键状态,决定是否执行按键扫描
CJNE A, #0, SNEXT1
;处于000态,按键未释放,退出(假设一次按键仅视为一次输入)
JB 02H,NEXT0001
JB 03H,NEXT0002
JB 01H,NEXT0003
SJMP KEXIT
NEXT0001:DJNZ MTIME,KEXIT
MOV MTIME,#20
LCALL LEFTPRO
SJMP KEXIT
NEXT0002:DJNZ MTIME,KEXIT
MOV MTIME,#20
LCALL RIGHTPRO
SJMP KEXIT
NEXT0003:LCALL KEYSCAN
SJMP KEXIT
SNEXT1:
CJNE A, #1, SNEXT2
;处于001态, 按键可能刚被释放,不处理
SJMP KEXIT
SNEXT2:
CJNE A, #2, SNEXT3
;处于010态,干扰,作000态处理
ANL KEYSTU, #00H
SJMP KEXIT
SNEXT3:
CJNE A, #3, SNEXT4
;处于011态,按键处于释放状态,退出
JB 04H,NEXT002
JB 05H,NEXT002
MOV 20H,#0 ;回到通常状态的总标志
CLR 15H
NEXT002:
SJMP SNEXT4
SNEXT4:
CJNE A, #4, SNEXT5
;处于100态,按键已经稳定闭合,进行按键扫描
LCALL KEYSCAN ;执行键盘扫描,确定哪一按键被按下
SJMP KEXIT
SNEXT5:
CJNE A, #5, SNEXT6
;处于101态, 干扰,作111态处理
ORL KEYSTU, #07H ;b2~b0位置1
SJMP KEXIT
SNEXT6:
CJNE A, #6, SNEXT7
;处于110态,按键刚被按下,未稳定,暂不处理
; LJMP EXIT
SNEXT7:
JB 04H,SNEXT8 ;调整数字闪动记数
JB 05H,SNEXT8
SJMP KEXIT
SNEXT8: INC FCOUNT
MOV A,FCOUNT
CJNE A,#10,SNEXT9
SNEXT9:JC KEXIT
MOV FCOUNT,#0
LCALL FLASHSCAN
;处于111态
KEXIT:
;将PD4~PD0置为高电平,使74HC273输出级截止,降低功耗。
MOV DPTR, #PORTD ;U105口地址送DPTR
MOV A, PORTDR ;读U105口在内存中的映象地址
ORL A, #1FH
MOVX @DPTR, A ;数据送U105输出口
;---键盘检测结束-----------
RET
END
PROC KEYSCAN ;键盘扫描程序
KEYSCAN:
MOV R7, #5 ;定义扫描次数
MOV R1, #0 ;初始化列地址
MOV R3, #01111111B ;扫描码初值
LOOP1:
;生成扫描码
MOV A, R3
RL A ;左移一位(从PD0开始扫描)
MOV R3, A ;保存扫描码
ANL A, #00011111B ;保留扫描
MOV B, A ;暂时保存在B寄存器中
MOV DPTR, #PORTD ;U105口地址送DPTR
MOV A, PORTDR ;读U105口在内存中的映象地址
ANL A, #0E0H ;保留与键盘扫描无关的b7~b5位。
ORL A, B ;与扫描或
MOVX @DPTR, A ;数据送U105输出口,将PD4~PD0置为低电平
NOP ;延迟一个机器周期等待输出口状态稳定
MOV DPTR, #PORTB ;B口地址送DPTR
MOVX A, @DPTR ;读B口
ANL A, #0FH ;屏蔽高4位
JB ACC.3, NEXT1
;ACC.0位为0,说明0行有按键被按下
MOV R2, #0 ;行地址为0
SJMP NEXT5
NEXT1:
JB ACC.2, NEXT2
;ACC.1位为0,说明1行有按键被按下
MOV R2, #1 ;行地址为1
SJMP NEXT5
NEXT2:
JB ACC.1, NEXT3
;ACC.2位为0,说明2行有按键被按下
MOV R2, #2 ;行地址为2
SJMP NEXT5
NEXT3:
JB ACC.0, NEXT4
;ACC.3位为0,说明3行有按键被按下
MOV R2, #3 ;行地址为3
SJMP NEXT5
NEXT4:
;说明该列上没有按键被按下
INC R1 ;列地址加+1,继续扫描
DJNZ R7, LOOP1
;扫描所有列,均没发现按按键被按下
LJMP EXIT999
NEXT5:
;计算行列地址,查表或区
MOV A, R1
RL A
RL A ;列地址乘4(每列对应4行)
ADD A, R2 ;加行地址
SLAP1:CJNE A,#0,SLAP2
LCALL PROMS ;1
LJMP EXIT999
SLAP2:CJNE A,#1,SLAP3
LCALL PRO3 ;1
LJMP EXIT999
SLAP3:CJNE A,#2,SLAP4
LCALL PRO6 ;1
LJMP EXIT999
SLAP4:CJNE A,#3,SLAP5
LCALL PRO9 ;1
LJMP EXIT999
SLAP5:CJNE A,#4,SLAP6
LCALL PRO0 ;1
LJMP EXIT999
SLAP6:CJNE A,#5,SLAP7
LCALL PRO2 ;1
LJMP EXIT999
SLAP7:CJNE A,#6,SLAP8
LCALL PRO5 ;1
LJMP EXIT999
SLAP8:CJNE A,#7,SLAP9
LCALL PRO8 ;1
LJMP EXIT999
SLAP9:CJNE A,#8,SLAP10
LCALL PRORIGHT ;1
LJMP EXIT999
SLAP10 :CJNE A,#9,SLAP11
LCALL PRO1 ;1
LJMP EXIT999
SLAP11:CJNE A,#10,SLAP12
LCALL PRO4 ;1
LJMP EXIT999
SLAP12:CJNE A,#11,SLAP13
LCALL PRO7 ;1
LJMP EXIT999
SLAP13:CJNE A,#12,SLAP14
LCALL PRODOWN ;1
LJMP EXIT999
SLAP14:CJNE A,#13,SLAP15
LCALL PROUP ;1
LJMP EXIT999
SLAP15:CJNE A,#14,SLAP16
LCALL PROYEAR ;1
LJMP EXIT999
SLAP16:CJNE A,#15,SLAP17
LCALL PROCHANG ;1
LJMP EXIT999
SLAP17:CJNE A,#16,SLAP18
LCALL PROLEFT ;1
LJMP EXIT999
SLAP18:CJNE A,#17,SLAP19
LCALL PROWEEK ;1
LJMP EXIT999
SLAP19:CJNE A,#18,SLAP20
LCALL PROAL ;1
LJMP EXIT999
SLAP20:CJNE A,#19,EXIT999
LCALL PROMD ;1
EXIT999:
RET
END
PROC PROMS
PROMS:
SETB 15H
RET
END
PROC PROWEEK
PROWEEK:MOV A,20H
JNZ EXIT00
SETB 00H
MOV DISPLAY2,#0
MOV DISPLAY1,WEEK
LCALL DISPLAY
MOV R0,#DISPBUF
MOV @R0,#0FFH
INC R0
MOV @R0,#0FFH
INC R0
MOV @R0,#0FFH
LCALL S_DISP
EXIT00:RET
END
PROC PROYEAR
PROYEAR:MOV A,20H
JNZ EXIT00
SETB 00H
MOV DISPLAY2,YEAR2
MOV DISPLAY1,YEAR1
LCALL DISPLAY
LCALL S_DISP
EXIT00:RET
END
;查询定时程序
PROC PROAL
PROAL:
MOV A,20H
JNZ EXIT124
;JB 07H,EXIT124
PUSH PSW
SETB RS0
CLR RS1
MOV DOWN,#0
MOV UP,#0
;CLR 07H
SETB 01H
MOV R0,#TIME1
MOV R1,#TIME01
MOV DISPLAY2,@R0
MOV DISPLAY1,@R1
LCALL DISPLAY
LCALL S_DISP
POP PSW
EXIT124:RET
END
;左键处理:04H=1,05H=0
PROC PROLEFT
PROLEFT:MOV A,20H
JZ LAP001
JNB 04H,EXIT43
JB 05H,EXIT43
MOV FLASHPLAY,#0
MOV A,DISCOUNT
CJNE A,#0,LAP408
MOV DISCOUNT,#3
MOV DISPLAY2,MINUTE
MOV DISPLAY1,SECOND
LCALL DISPLAY
LCALL S_DISP
SJMP EXIT43
LAP408: DEC DISCOUNT
MOV A,DISCOUNT
ADD A,DISCOUNT
MOV R0,#YEAR2
ADD A,R0
MOV R0,A
MOV DISPLAY2,@R0
INC R0
MOV DISPLAY1,@R0
LCALL DISPLAY
LCALL S_DISP
SJMP EXIT43 ;左键处理程序 传递参数:用到1区R1
LAP001:
PUSH PSW
SETB RS0
CLR RS1
SETB 02H
SETB 12H
MOV MTIME,#20
MOV R1,#3DH
;MOV DISPLAY2,MINUTE
;MOV DISPLAY1,SECOND
;LCALL DISPLAY
;LCALL S_DISP
POP PSW
EXIT43:RET
END
;查询左键 左移半字节的指令。用第1区R2传递参数
PROC LEFTPRO ;接受来自的R1参数
LEFTPRO:PUSH PSW
SETB RS0
CLR RS1
JNB 12H,LAP31
LCALL RIGHT_1
DEC R1
MOV A,@R1
MOV B,#10
DIV AB
MOV R2,A
XCH A,B
MOV DPTR,#LEDTAB
MOV R0,#DISPBUF
MOVC A,@A+DPTR
MOV @R0,A
LCALL S_DISP
CPL 12H
SJMP EXIT31
LAP31:
LCALL RIGHT_1
MOV A,R2
MOV DPTR,#LEDTAB
MOVC A,@A+DPTR
MOV R0,#DISPBUF
MOV @R0,A
LCALL S_DISP
CPL 12H
CJNE R1,#YEAR1,LOOP31
LOOP31:JNC EXIT31
MOV R1,#SECOND+1
EXIT31:POP PSW
RET
END
;查询左键右移指令:右移一位。用到第2区的R0,R1,R7
PROC RIGHT_1
RIGHT_1:PUSH PSW
SETB RS1
CLR RS0
MOV R0,#DISPBUF+3
MOV R1,#DISPBUF+2
MOV R7,#3
LOOP3:MOV A,@R1
MOV @R0,A
DEC R0
DEC R1
DJNZ R7,LOOP3
POP PSW
RET
END
;右键处理:04H=1,05H=0
PROC PRORIGHT
PRORIGHT:MOV A,20H
JZ LAP002
JNB 04H,EXIT44
JB 05H,EXIT44
MOV FLASHPLAY,#0
MOV A,DISCOUNT
CJNE A,#3,LAP409
LAP409:JC LAP410
MOV DISCOUNT,#0
MOV DISPLAY2,YEAR2
MOV DISPLAY1,YEAR1
LCALL DISPLAY
LCALL S_DISP
SJMP EXIT44
LAP410:INC DISCOUNT
MOV A,DISCOUNT
ADD A,DISCOUNT
MOV R0,#YEAR2
ADD A,R0
MOV R0,A
MOV DISPLAY2,@R0
INC R0
MOV DISPLAY1,@R0
LCALL DISPLAY
LCALL S_DISP
SJMP EXIT44 ;查询右键处理程序
LAP002: PUSH PSW
SETB RS0
CLR RS1
SETB 03H
SETB 12H
MOV MTIME,#20
MOV R1,#YEAR1
MOV DISPLAY2,YEAR2
MOV DISPLAY1,YEAR1
LCALL DISPLAY
LCALL S_DISP
POP PSW
EXIT44: RET
END
;查询右移指令:传递半字节的显示参数。用第1区传递参数
PROC RIGHTPRO
RIGHTPRO:PUSH PSW
SETB RS0
CLR RS1
JNB 12H,LAP31
LCALL LEFT_1
INC R1
MOV A,@R1
MOV B,#10
DIV AB
MOV R2,B
MOV DPTR,#LEDTAB
MOV R0,#DISPBUF+3
MOVC A,@A+DPTR
MOV @R0,A
LCALL S_DISP
CPL 12H
SJMP EXIT31
LAP31:
LCALL LEFT_1
MOV A,R2
MOV DPTR,#LEDTAB
MOVC A,@A+DPTR
MOV R0,#DISPBUF+3
MOV @R0,A
LCALL S_DISP
CPL 12H
CJNE R1,#3FH,LOOP31
LOOP31:JC EXIT31
MOV R1,#YEAR2-1
EXIT31: POP PSW
RET
END
;查询右移指令:左移一位。用到第2区的R0,R1,R7
PROC LEFT_1
LEFT_1:PUSH PSW
SETB RS1
CLR RS0
MOV R0,#DISPBUF
MOV R1,#DISPBUF+1
MOV R7,#3
LOOP3:MOV A,@R1
MOV @R0,A
INC R0
INC R1
DJNZ R7,LOOP3
POP PSW
RET
END
PROC PROMD
PROMD: MOV A,20H
JNZ EXIT01
SETB 00H
MOV DISPLAY2,MONTH
MOV DISPLAY1,DAY
LCALL DISPLAY
LCALL S_DISP
EXIT01:RET
END
;查询定时程序:下键处理程序
PROC PRODOWN
PRODOWN:JNB 01H,LAP004
PUSH PSW
SETB RS0
CLR RS1
;SETB 07H
INC DOWN
MOV A,DOWN
CJNE A,#20,LAP20
LAP20: JC LAP21
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -