键盘扫描程序段
OUTBIT equ 08002h ; 列地址
IN equ 08001h ; 行地址
Delay: ; 延时子程序
mov r7, #0
DelayLoop:
djnz r7, DelayLoop
djnz r6, DelayLoop
ret
TestKey:
mov dptr, #OUTBIT
mov a, #0
movx @dptr, a ; 输出线置为0
mov dptr, #IN
movx a, @dptr ; 读入键状态
cpl a
anl a, #0fh ; 高四位不用
ret
KeyTable: ; 键码定义
db 16h, 15h, 14h, 0ffh
db 13h, 12h, 11h, 10h
db 0dh, 0ch, 0bh, 0ah
db 0eh, 03h, 06h, 09h
db 0fh, 02h, 05h, 08h
db 00h, 01h, 04h, 07h
GetKey:
mov dptr, #OUTBIT
mov P2, dph
mov r0, #Low(IN)
mov r1, #00100000b
mov r2, #6
KLoop:
mov a, r1 ; 找出键所在列
cpl a
movx @dptr, a
cpl a
rr a
mov r1, a ; 下一列
movx a, @r0
cpl a
anl a, #0fh
jnz Goon1 ; 该列有键入
djnz r2, KLoop
mov r2, #0ffh ; 没有键按下, 返回 0ffh
sjmp Exit
Goon1:
mov r1, a ; 键值 = 列 X 4 + 行
mov a, r2
dec a
rl a
rl a
mov r2, a ; r2 = (r2-1)*4
mov a, r1 ; r1 中为读入的行值
mov r1, #4
LoopC:
rrc a ; 移位找出所在行
jc Exit
inc r2 ; r2 = r2+ 行值
djnz r1, LoopC
Exit:
mov a, r2 ; 取出键码
mov dptr, #KeyTable
movc a, @a+dptr
mov r2, a
WaitRelease:
mov dptr, #OUTBIT ; 等键释放
clr a
movx @dptr, a
mov r6, #10
call Delay
call TestKey
jnz WaitRelease
mov a, r2
ret
OUTBIT equ 09002h ; 列地址
IN equ 09001h ; 行地址
CWADD1 EQU 8000H ;写指令代码地址(E1)
DWADD1 EQU 8001H ;写显示数据地址(E1)
CRADD1 EQU 8002H ;读状态字地址(E1)
DRADD1 EQU 8003H ;读显示数据地址(E1)
CWADD2 EQU 8004H ;写指令代码地址(E2)
DWADD2 EQU 8005H ;写显示数进地址(E2)
CRADD2 EQU 8006H ;读状态字地址(E2)
DRADD2 EQU 8007H ;读显示数据地址(E2)
KEY_VALUE EQU 29H ;键值
PD1 EQU 28H ;122/2 分成左右两半屏 122x32
COLUMN EQU 27H ;
PAGE_SED EQU 26H ;页地址寄存器 D1,DO:页地址
CODE_SED EQU 25H ;字符代码寄存器
COUNT EQU 24H ;计数器
DIR equ 23h
CTEMP EQU 22H
COM EQU 21H ;指令寄存器
DAT EQU 20H ;数据寄存器
ORG 0000H
LJMP start
start: mov sp,#60h
key_loop: lcall testkey
jz key_loop
lcall getkey
cjne a,#10h,no_show1
no_show1: jnc no_show2
mov key_value,a
lcall exe_key
no_show2: sjmp key_loop
Delay: ; 延时子程序
mov r7, #0
DelayLoop:
djnz r7, DelayLoop
djnz r6, DelayLoop
ret
TestKey:
mov dptr, #OUTBIT
mov a, #0
movx @dptr, a ; 输出线置为0
mov dptr, #IN
movx a, @dptr ; 读入键状态
cpl a
anl a, #0fh ; 高四位不用
ret
KeyTable: ; 键码定义
db 16h, 15h, 14h, 0ffh
db 13h, 12h, 11h, 10h
db 0dh, 0ch, 0bh, 0ah
db 0eh, 03h, 06h, 09h
db 0fh, 02h, 05h, 08h
db 00h, 01h, 04h, 07h
GetKey:
mov dptr, #OUTBIT
mov P2, dph
mov r0, #Low(IN)
mov r1, #00100000b
mov r2, #6
KLoop:
mov a, r1 ; 找出键所在列
cpl a
movx @dptr, a
cpl a
rr a
mov r1, a ; 下一列
movx a, @r0
cpl a
anl a, #0fh
jnz Goon1 ; 该列有键入
djnz r2, KLoop
mov r2, #0ffh ; 没有键按下, 返回 0ffh
sjmp Exit
Goon1:
mov r1, a ; 键值 = 列 X 4 + 行
mov a, r2
dec a
rl a
rl a
mov r2, a ; r2 = (r2-1)*4
mov a, r1 ; r1 中为读入的行值
mov r1, #4
LoopC:
rrc a ; 移位找出所在行
jc Exit
inc r2 ; r2 = r2+ 行值
djnz r1, LoopC
Exit:
mov a, r2 ; 取出键码
mov dptr, #KeyTable
movc a, @a+dptr
mov r2, a
WaitRelease:
mov dptr, #OUTBIT ; 等键释放
clr a
movx @dptr, a
mov r6, #10
call Delay
call TestKey
jnz WaitRelease
mov a, r2
ret
; 8*16点阵字符显示程序段
EXE_KEY: LCALL INIT
LCALL CLEAR
MOV CTEMP,#0
MOV DIR,#0
MOV PAGE_SED,#00H
MOV COLUMN,#0
MOV CODE_SED,KEY_VALUE
LCALL WRI_EN816
RET
;---------------------------------------
; 初始化程序
INIT: MOV COM, #0E2H ;复位
LCALL PR0
LCALL PR3
MOV COM, #0A4H ;关闭休闭状态
LCALL PR0
LCALL PR3
MOV COM, #0A9H ;设置 1/32 占空比
LCALL PR0
LCALL PR3
MOV COM, #0A0H ;正向排序设置
LCALL PR0
LCALL PR3
MOV COM, #0C0H ;设置显示起始行为第一行
LCALL PR0
LCALL PR3
MOV COM, #0AFH ;开显示设置
LCALL PR0
LCALL PR3
RET
;------------------------------------------------
; 清屏
CLEAR: MOV R4,#00H ;页面地址暂存器设置
CLEAR1: MOV A,R4 ;取页地址值
ORL A,#0B8H ;"或"页面地址设置代码
MOV COM,A ;页面地址设置
LCALL PR0
LCALL PR3
MOV COM,#00H ;列地址设置为"0"
LCALL PR0
LCALL PR3
MOV R3,#50H ;一页清 80个字节
CLEAR2: MOV DAT,#00H ;显示数据为"0"
LCALL PR1
LCALL PR4
DJNZ R3,CLEAR2 ;页内字节清零循环
INC R4 ;页地址暂存器加一
CJNE R4,#04H,CLEAR1;RAM 区清零循环
RET
;-----------------------------------
;1.写指令代码子程序(E1)
PR0: PUSH DPL
PUSH DPH
MOV DPTR,#CRADD1 ;设置读状态字地址
PR01: MOVX A,@DPTR ;读状态字
JB ACC.7,PR01 ;判"忙"标志为句"0",否再读
MOV DPTR,#CWADD1 ;设置写指令代码地址
MOV A,COM ;取指令代码
MOVX @DPTR,A ;写指令代码
POP DPH
POP DPL
RET
;------------------------------------
;2.写显示数据子程序(E1)
PR1: PUSH DPL
PUSH DPH
MOV DPTR,#CRADD1 ;设置读状态字地址
PR11: MOVX A,@DPTR ;读状态宇
JB ACC.7,PR11 ;判"忙"标志为"0",否再读
MOV DPTR,#DWADD1 ;设置写显示数据地址
MOV A,DAT ;取数据
MOVX @DPTR,A ;写数据
POP DPH
POP DPL
RET
;-------------------------------------
;3.读显示数据子程序(E1)
PR2: PUSH DPL
PUSH DPH
MOV DPTR,#CRADD1 ;设置读状态字地址
PR21: MOVX A,@DPTR ;读状态字
JB ACC.7,PR21 ;判"忙"标志为"0"否,否再读
MOV DPTR,#DRADD1 ;设置读显示数据地址
MOVX A,@DPTR ;读数据
MOV DAT,A ;存数据
POP DPH
POP DPL
RET
;-------------------------------------
;4.写指令代码子程序(E2)
PR3: PUSH DPL
PUSH DPH
MOV DPTR,#CRADD2 ;设置读状态字地址
PR31: MOVX A,@DPTR ;读状态字
JB ACC.7,PR31 ;判"忙"陈志为"0"否,否再读
MOV DPTR,#CWADD2 ;设置写指令代码地址
MOV A,COM ;取指令代码
MOVX @DPTR,A ;写指令代码
POP DPH
POP DPL
RET
;-------------------------------------
; 5.写显示数据子程序(E2)
PR4: PUSH DPL
PUSH DPH
MOV DPTR,#CRADD2 ;设置读状态字地址
PR41: MOVX A,@DPTR ;读状态字
JB ACC.7,PR41 ;判"忙"标志为"0"否,否再读
MOV DPTR, #DWADD2 ;设置写显示数据地址
MOV A,DAT ;取数据
MOVX @DPTR,A ;写数据
POP DPH
POP DPL
RET
;---------------------------------------
; 6.读显示数据子程序(E2)
PR5: PUSH DPL
PUSH DPH
MOV DPTR,#CRADD2 ;设置读状态字地址
PR51: MOVX A,@DPTR ;读状态字
JB ACC.7,PR51 ;判"忙"标志为"0",否再读
MOV DPTR,#DRADD2 ;设置写显示数据地址
MOVX A,@DPTR ;读数据
MOV DAT,A ;存数据
POP DPH
POP DPL
RET
; 8*16点阵字符显示程序段
WRI_EN816: MOV DPTR,#CCTAB ;确定字符字模块首地址
MOV A,CODE_SED ;取代码
MOV B,#10H ;字模块宽度为16个字节
MUL AB ;代码×16
ADD A,DPL ;字符字模块首地址
MOV DPL,A ;字模库首地址+代码×16
MOV A,B
ADDC A,DPH
MOV DPH,A
CLR 50H
PUSH COLUMN
PUSH COLUMN
MOV CODE_SED,#00H ;代码寄存器借用为间址寄存器
WRI_1: MOV COUNT,#8H ;计数器设置为8
MOV A,PAGE_SED ;读页地址寄存器
ANL A,#03H ;取页地址有效值
ORL A,#0B8H ;"或"页地址设置代码
MOV COM,A ;设置页地址
LCALL PR0
LCALL PR3
POP COLUMN
MOV A,COLUMN ;读列地址寄存器
CLR C
SUBB A,#PD1 ;列地址-模块参数
JC WRI_2 ;<0为左半屏显示区域(E1)
MOV COLUMN,A ;≥0为右半屏显示区域(E2)
SETB 50H ;设置区域标志位。
WRI_2: MOV COM,COLUMN ;设置列地址值
JNB 50H,WRI_3
LCALL PR3 ;区域E2
SJMP WRI_4
WRI_3: LCALL PR0 ;区域E1
WRI_4: MOV A,CODE_SED ;取间址寄存器值
MOVC A,@A+DPTR ;取汉字字模数据
MOV DAT,A ;写数据
;MOV A,PAGE_SED
JNB 50H,WRI_5
LCALL PR4 ;区域E2
SJMP WRI_6
WRI_5: LCALL PR1 ;区域E1
WRI_6: INC CODE_SED ;间址寄存器加一
INC COLUMN ;列地址寄存器加一
MOV A,COLUMN ;判列地址是否超出区域范围、
CJNE A,#PD1,WRI_7
WRI_7: JC WRI_8 ;未超出则继续
JB 50H,WRI_8 ;在区域E2 则退出
SETB 50H ;在区域E1 则修改成区域E2
MOV COM,#00H ;设置区域E2列地址为"0"
LCALL PR3
WRI_8: DJNZ COUNT,WRI_4 ;当页循环
MOV A,PAGE_SED ;读页地址寄存器
JB ACC.7,WRI_9 ;判完成标志D7 位,"1"则完成退出
INC A ;否则页地址加一
SETB ACC.7 ;置完成位为"1"
MOV PAGE_SED,A
CLR 50H
MOV CODE_SED,#8H ;间址寄存器设置为8
LJMP WRI_1 ;大循环
WRI_9: RET
;--------------------------------------
;字符库
CCTAB:
;0
DB 0F8H,0FCH,004H,0C4H,024H,0FCH,0F8H,000H
DB 007H,00FH,009H,008H,008H,00FH,007H,000H
;1
DB 000H,010H,018H,0FCH,0FCH,000H,000H,000H
DB 000H,008H,008H,00FH,00FH,008H,008H,000H
;2
DB 008H,00CH,084H,0C4H,064H,03CH,018H,000H
DB 00EH,00FH,009H,008H,008H,00CH,00CH,000H
;3
DB 008H,00CH,044H,044H,044H,0FCH,0B8H,000H
DB 004H,00CH,008H,008H,008H,00FH,007H,000H
;4
DB 0C0H,0E0H,0B0H,098H,0FCH,0FCH,080H,000H
DB 000H,000H,000H,008H,00FH,00FH,008H,000H
;5
DB 07CH,07CH,044H,044H,0C4H,0C4H,084H,000H
DB 004H,00CH,008H,008H,008H,00FH,007H,000H
;6
DB 0F0H,0F8H,04CH,044H,044H,0C0H,080H,000H
DB 007H,00FH,008H,008H,008H,00FH,007H,000H
;7
DB 00CH,00CH,004H,084H,0C4H,07CH,03CH,000H
DB 000H,000H,00FH,00FH,000H,000H,000H,000H
;8
DB 0B8H,0FCH,044H,044H,044H,0FCH,0B8H,000H
DB 007H,00FH,008H,008H,008H,00FH,007H,000H
;9
DB 038H,07CH,044H,044H,044H,0FCH,0F8H,000H
DB 000H,008H,008H,008H,00CH,007H,003H,000H
;A
DB 0E0H,0F0H,098H,08CH,098H,0F0H,0E0H,000H
DB 00FH,00FH,000H,000H,000H,00FH,00FH,000H
;B
DB 004H,0FCH,0FCH,044H,044H,0FCH,0B8H,000H
DB 008H,00FH,00FH,008H,008H,00FH,007H,000H
;C
DB 0F0H,0F8H,00CH,004H,004H,00CH,018H,000H
DB 003H,007H,00CH,008H,008H,00CH,006H,000H
;D
DB 004H,0FCH,0FCH,004H,00CH,0F8H,0F0H,000H
DB 008H,00FH,00FH,008H,00CH,007H,003H,000H
;E
DB 004H,0FCH,0FCH,044H,0E4H,00CH,01CH,000H
DB 008H,00FH,00FH,008H,008H,00CH,00EH,000H
;F
DB 004H,0FCH,0FCH,044H,0E4H,00CH,01CH,000H
DB 008H,00FH,00FH,008H,000H,000H,000H,000H
;------------------------------------.