KEYS EQU 5AH ;记录键值
KEY1 EQU 5BH ;记录行扫描时的值
KEY2 EQU 5CH ;记录列扫描时的值
ORG 0000H ;程序开始
AJMP START
ORG 30H ;为避免占用中断向量区,主程序从30H开始
START:
MOV SP,#5FH ;设置堆栈的初始地址
MOV P3,#0FH ;P3,P2,P0的初始化
MOV P2,#00H
MOV P0,#0FFH
MOV KEYS,#00H ;各键值清0
MOV KEY1,#00H
MOV KEY2,#00H
CLR KEYCARD ;有按键标志清0
LOOP: ;循环扫描键盘
ACALL KEY_CHECK
JNB KEYCARD,LOOP
ACALL KEY_VAL ;如果有键按下,则确定是哪一个键按下
AJMP LOOP
KEY_CHECK: ;看有没有键按下
MOV A,P3
ANL A,#0FH
CJNE A,#0FH,KEY_CER ;如果读入的与写出的不相等,延时消抖
CLR KEYCARD
RET
KEY_CER: ;延时,再读入,看是否真的有键按下
ACALL DELAY1S
MOV A,P3
ANL A,#0FH
CJNE A,#0FH,KEY_CE
CLR KEYCARD
RET
KEY_CE:
SETB KEYCARD ;真的有键按下,则置标志位
RET
KEY_VAL: ;用于获得键值码
MOV P3,#0FH
MOV A,P3
MOV KEY1,A ;行键值码
ANL A,#0FH
CJNE A,#0FH,KEY_M1 ;确定有键按下,则确定列键值码,否则退出
AJMP KEY_EXIT
KEY_M1:
MOV P3,#0F0H
MOV A,P3
MOV KEY2,A ;列键值码
ANL A,#0F0H
CJNE A,#0F0H,KEY_M2 ;如果又确定到有列键值码,则查表获得键值
AJMP KEY_EXIT
KEY_M2:
MOV A,KEY2
MOV R0,#KEY1
XCHD A,@R0
MOV KEYS,A
MOV R0,#00H
DISPLAY:
MOV A,R0
INC R0
MOV DPTR,#KEY_VALUE ;根据键码查键值
MOVC A,@A+DPTR
CJNE A,KEYS,DISPLAY ;直到查到对应的键值
DEC R0
MOV A,R0 ;把键值赋值给R0
MOV DPTR,#TAB
MOVC A,@A+DPTR
MOV KEYS,A
MOV P2,#10H ;选通P2.4准备显示
MOV P0,A ;把显示码送到P0
ACALL DELAY1S
KEY_EXIT: ;用于退出键盘扫描
CLR KEYCARD
RET
DELAY1S: ;延时函数
MOV R7,#10
D1:
MOV R6,#50
DJNZ R6,$
DJNZ R7,D1
RET
KEY_VALUE: ;键值表
DB 0EBH,0DBH,0BBH,7BH,0E7H,0D7H,0B7H,77H
TAB: ;显示码
DB 0xEF,0xDF,0xBF,0x7F,0xFE,0xFD,0xFB,0xF7
END