;######键盘扫描子程序 SCANKEY ###########
;需要寄存器:R2,R3,R4,R5,R6
;R2-计数,R4-行号,R3-列号,R5-扫描码,R6-计数
;入口:无
;出口:KEYNUM,无键值KEYNUM中为'0FFH',有键值KEYNUM中为键值
;键值计算:(4-列号)*3+行号
;需调用函数:10MS延时函数 DLY10MS
;######################################
SCANKEY:LCALL KEXAM ;判断是否有键按下,A中为零则无键按下,非零则有键按下
JNZ SCANK0 ;有键则转
MOV KEYNUM,#0FFH ;无键按下 KEYNUM EQU 11H ;键号
LJMP ESCANK ;转返回
SCANK0: LCALL DLY10MS ;有键按下,延时去抖
LCALL KEXAM ;再次判断是否有键按下,有键按下时A中为非零值
JNZ SCANK1 ;有键按下则转
MOV KEYNUM,#0FFH ;无键按下
LJMP ESCANK
SCANK1: MOV R4,#00H ;行号
MOV R6,#03H ;扫描行数
MOV R5,#0EFH ;第一行扫描码
SCAN10: MOV A,R5 ;输出扫描码
MOV P1,A
MOV A,P1
CPL A ;
ANL A,#0FH
JNZ CHK1 ;本行有键按下
LJMP CHK2 ;本行无键按下
CHK1: MOV R2,#4 ;扫描列数
CHK10: JB ACC.0,CALK1 ;该列有键按下则转
RR A
DJNZ R2,CHK10 ;检测按键所在列
CHK2: MOV A,R5
RL A
MOV R5,A ;修正扫描码
INC R4 ;行号加1
DJNZ R6,SCAN10 ;扫描下一行
MOV KEYNUM,#0FFH ;未检测到按键
LJMP ESCANK ;返回
CALK1: CLR C ;计算键值
MOV A,#4
SUBB A,R2 ;计算列号
MOV B,#03H
MUL AB
ADD A,R4 ;计算键值
MOV KEYNUM,A ;存键值
KEYNO: LCALL DLY10MS ;
LCALL KEXAM ;发全扫描信号
JNZ KEYNO ;健未释放则等待
LCALL DLY10MS ;延时消抖
ESCANK: RET
;#########
;功能:判断是否有键被按下
;入口参数:无
;出口参数:A中为零则无键按下,非零则有键按下
;######################
KEXAM: MOV P1,#8FH
MOV A,P1
CPL A
ANL A,#0FH
RET