ORG 0000H
START: LJMP MAIN
ORG 000BH
LJMP PDJW ;****************************************************************;
;系统监控程序区
ORG 0030H
MAIN: MOV PSW, #00H
MOV SP, #7FH ;确立堆栈区
MOV R0, #20H ;RAM区首地址
MOV R7, #96 ;RAM区单元个数
MOV TMOD, #01H SETB EA SETB ET0
ML: MOV @R0, #00H
INC R0
DJNZ R7, ML
TSF: MOV DPTR, #DISBH ;系统初始化后提示符“P.”字符
代码表首地址 MOV R5, #08H
MOV R0, #78H
DISPTSF:CLR A
MOVC A, @A+DPTR
MOV @R0, A
INC R0
INC DPTR
DJNZ R5, DISPTSF
KEY0: LCALL DISP
LCALL KEY
JB 20H.0, K1
JB 20H.1, K2
JB 20H.2, K3
LJMP KEY0
KEY00: LCALL KEY
LCALL DISP
JB 20H.2, K3
LJMP KEY00
K1: JB 22H.1, KEY0 ;如果此时为暂停状态,本次按键K1无效
CPL 22H.0
JB 22H.0, K01 ;高电平则计时
CLR TR0 ;低电平则停止
LCALL DISP
LJMP KEY00
K01: MOV 7AH, #12H ;从零开始计时
MOV 7DH, #12H
MOV 7FH, #10H
MOV 78H, #00H
MOV 79H, #00H
MOV 7BH, #00H
MOV 7CH, #00H
MOV 7EH, #00H
MOV 7FH, #00H
LCALL DISP
MOV TH0, #0D8H
MOV TL0, #0F0H
SETB TR0 ;启动定时器
LJMP KEY0
K2: JB 22H.0, K21 ;判断秒表是否启动,如不是启动
状态则此次按键无效
LJMP KEY0
K21: CPL 22H.1
JB 22H.1, K22
SETB TR0 ;继续计时
LJMP KEY0
K22: CLR TR0 ;暂停秒表
LCALL DISP
LJMP KEY0
K3: JB 22H.0, KEY0 ;只有当停止是,清零键才有效
MOV R0, #79H ;秒表清零
LCALL CLR00
MOV R0, #7CH
LCALL CLR00
MOV R0, #7FH
LCALL CLR00
LJMP KEY0
PDJW: PUSH PSW
PUSH ACC
MOV TMOD, #01H ;定时器以工作方式1工作
SETB RS1 ;设定组号为2组
CLR RS0
MOV TH0, #0D8H
MOV TL0, #0F0H
MOV R0, #79H
LCALL ADD01
CJNE R2, #99, RETT ;判断1秒到没
MOV R0, #7CH
LCALL ADD01
CJNE R2, #60, RETT ;判断60毫秒到没
LCALL CLR00
MOV R0, #7FH
LCALL ADD01
CJNE R2, #60H, RETT ;判断60分到没
LCALL CLR00
RETT: POP ACC
POP PSW
RETI
;*****************************************************************;
;常数表格区
;系统初始化后提示符“P.”字符代码表;
DISBH: DB 10H,10H,10H,10H,10H,10H,10H,11H ;提示符“P.”字符序号
;显示字符段选码表(共阳极代码)
TAB: DB 0C0H, 0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H ;0-8
DB 90H, 88H,83H,0C6H,0A1H,86H,8EH,0FFH,0CH,0BFH ;9,A,B,C,D,E,F,
灭,p.,-
;*******************************************************************;
;子程序区;
ADD01: MOV A, @R0
DEC R0
SWAP A
ORL A, @R0
ADD A, #01H
DA A
MOV R2, A
ANL A, #0FH
MOV @R0, A
MOV A, R2
ANL A, #0F0H
SWAP A
INC R0
MOV @R0, A
RET
CLR00: MOV @R0, #00H
DEC R0
MOV @R0, #00H
RET
;键扫描子程序
KEY: LCALL KEYCHULI ;调P1口数据处理子程序
JZ EXIT ;没有键按下,转返回
LCALL DISP ;调显示子程序去抖动
LCALL DISP
LCALL KEYCHULI ;调P1口数据处理子程序
JZ EXIT ;没有键按下,转返回
MOV B, 20H ;保存取反后的键值
KEYSF: LCALL KEYCHULI ;调P1口数据处理子程序
JZ KEY1 ;键释放,转恢复键值
LCALL DISP
LCALL DISP ;调显示子程序延时
LJMP KEYSF ;等待释放
KEY1: MOV 20H, B ; 键值送20H保存
EXIT: RET ;子程序返回
;P1口数据处理子程序
KEYCHULI:PUSH PSW ;保护现场
CLR RS1 ;改变当前寄存器组为组
SETB RS0
MOV P1, #0FFH ;先向P1口写1
MOV A, P1 ;读P1口数据
CPL A ;P1口数据取反
MOV 20H, A ;保存取反后的键值
CLR RS1 ;恢复当前寄存器组为组0
CLR RS0
POP PSW ;恢复现场
RET ;子程序返回
;显示子程序
;入口: 78H,79H,7AH,7BH,7CH,7DH,7EH,7FH,
DISP: PUSH DPH
PUSH DPL
PUSH ACC
PUSH PSW
CLR RS1 ;改变当前寄存器组为组1
SETB RS0
MOV R1, #78H ;显示缓冲存储单元首地址
MOV R2, #0FEH ;从右至左显示
MOV R5, #08H ;循环次数,即驱动数码管的位数
DISP1: MOV A, @R1
MOV DPTR, #TAB
MOVC A, @A+DPTR
MOV P0, A ;送段控
MOV P2, R2 ;送位控
LCALL DL ;延时1毫秒
MOV A, R2 ;位控码送A
RL A ;获得新的位控码
MOV R2, A ;保存新的位控码
INC R1 ;获得新的显示缓冲单元地址
DJNZ R5, DISP1 ;循环没有结束则继续
DISP2: POP PSW ;恢复当前寄存器组的组号
POP ACC
POP DPL
POP DPH
RET
;延时1ms子程序(晶振频率12MHz)DL
DL: MOV R7, #02H
DL1: MOV R6, #0FFH
DL2: DJNZ R6, DL2
DJNZ R7, DL1
RET
END
|