📄 key_scan.asm
字号:
;********************************************************
;*程序功能:在单片机教学实验仪的MCU#3上 *
;*对矩阵按键进行扫描检测,将检测到的键号 *
;*以移位的形式显示在8个数码管上 *
;* *
;********************************************************
ORG 0000H
JMP MAIN
;==================================
;RAM区变量定义
UP_DOWN BIT 00 ;键状态指示,0按下,1弹起
DISBUF EQU 30H ;显示参数传递
POSIT EQU 38H ;位选
KEYBUF EQU 39H ;键码暂存
KEYTEMP EQU 40H ;暂存待确定的扫描码
;===================================
;主函数
ORG 0030H
MAIN:
SETB UP_DOWN ;初始设置为弹起态
MOV DISBUF,#01H ;在第1个数码管上显示 1
MOV DISBUF+1,#02H ;在第2个数码管上显示 2
MOV DISBUF+2,#03H ;在第3个数码管上显示 3
MOV DISBUF+3,#04H ;在第4个数码管上显示 4
MOV DISBUF+4,#05H ;在第5个数码管上显示 5
MOV DISBUF+5,#06H ;在第6个数码管上显示 6
MOV DISBUF+6,#07H ;在第7个数码管上显示 7
MOV DISBUF+7,#08H ;在第8个数码管上显示 8
LOOP:
CALL KEY ;查键
CALL DISPLAY ;显示
JMP LOOP
;==================================
;8路数码管驱动
DISPLAY:
MOV POSIT,#80H ;用于指示数码管位选,初始化为第一个数码管亮
MOV R1,#08H ;用于指示程序循环,8个数码管每个送一次数后,本子程序结束
MOV DPTR,#DISCODE ;指向数码管的码表
MOV R0,#DISBUF ;指向显示数组
DISLOOP: ;为方便起见,只将第一个数码管的执行过程讲明,其余依次类推
MOV A,@R0 ;当R0=#DISBUF时,通过间接寻址将DISBUF中的内容放入A中
MOVC A,@A+DPTR ;通过查表,A为地址偏移量,找出A中的数所对应的码值(即段码),还放在A中
MOV P0,A ;将A中的数送至P0端口,单此时并未送至数码管
CALL SEGLOCK ;锁存数码管的段码
MOV P0,POSIT ;送位选至P0,以便指示哪一个数码管亮
CALL BITLOCK ;锁存数码管的位选信号
CALL DELAY ;使相应数码管亮一段时间
MOV P0,#00H ;送位选为00至P0口,即关闭所有的数码管,一产生消隐作用,避免数码管上产生重影现象
CALL BITLOCK ;锁存消隐信号
MOV A,POSIT ;当一个数码管完成显示后,对位选进行移位操作,以便为下一个数码管
RR A ;的显示作好准备,此时,位选指向下一个数码管
MOV POSIT,A
INC R0 ;使R0的数自加一,指向下一个要显示的数字,若上一次指向DISBUF,则
DJNZ R1,DISLOOP ;本次指向DISBUF+1,并受R1控制,完成8个数在数码管上的显示
RET ;所以,在使用此显示程序时,只需将欲显示的数字放入对应的DISBUF即可
;=============================
;数码管移位
POSI_CH:
MOV R0,#DISBUF
MOV R1,#DISBUF+1 ;将DISBUF中的数,从高位到低位
UU: ;依次覆盖
MOV A,@R1 ;然后将得到的最新键植
MOV @R0,A ;装入DISBUF+7
INC R0
INC R1
CJNE R0,#POSIT,UU
MOV R1,#POSIT-1
MOV A,R7
MOV @R1,A
RET
;===================================
;延时程序
DELAY:
MOV R3,#0FH
LOOP1: DJNZ R3,LOOP1
NOP
RET
;===================================
;锁存数码管段码
SEGLOCK:
SETB P1.3
NOP
CLR P1.3
RET
;===================================
;锁存数码管位选
BITLOCK:
SETB P1.2
NOP
CLR P1.2
RET
;===================================
;按键检测
KEY_SCAN:
MOV P2,#0FH ;列扫描
MOV KEYBUF,P2
MOV P2,#0F0H ;行扫描
MOV A,P2
ORL A,KEYBUF ;将最新的扫描码放在A中
RET
;===================================
;判断按键状态
KEY:
JB UP_DOWN,KEY_DOWN_CHECH ;检测当前按键的状态,若为弹起状态,则检测键按下
JMP KEY_UP_CHECH ;若为按下状态,则检测键弹起
KEY_DOWN_CHECH:
CALL KEY_SCAN
CJNE A,#0FFH,KEY_CHECH ;有键按下否?
JMP KEY_END ;没有,返回主函数
KEY_CHECH:
CALL KEY_SCAN
MOV KEYTEMP,A ;存放最新的扫描码以被确认
CALL DELAY_KEY ;有,延时去抖
CALL KEY_SCAN ;重新检测键状态
CJNE A,KEYTEMP,KEY_END ;如和上次扫描的一样,说明确实有键按下
CALL KEY_SERCH
CALL POSI_CH
CLR UP_DOWN ;只对键号码表进行16次比对,找不到
JMP KEY_END ;也要终止比较
KEY_UP_CHECH: ;按键弹起检测
CALL KEY_SCAN
CJNE A,#0FFH,KEY_END
SETB UP_DOWN ;给出当前按键状态
KEY_END:
RET
;===================================
;按键去抖延时
DELAY_KEY:
MOV R3,#0FH
L1: MOV R7,#0FFH
L2: DJNZ R7,L2
DJNZ R3,L1
RET
;===================================
;键号查询
KEY_SERCH:
CJNE A,#0DEH,KEY1 ;0键查询
JMP KEY0_SR
KEY1:
CJNE A,#0E7H,KEY2 ;1键查询
JMP KEY1_SR
KEY2:
CJNE A,#0D7H,KEY3 ;2键查询
JMP KEY2_SR
KEY3:
CJNE A,#0B7H,KEY4 ;3键查询
JMP KEY3_SR
KEY4:
CJNE A,#0EBH,KEY5 ;4键查询
JMP KEY4_SR
KEY5:
CJNE A,#0DBH,KEY6 ;5键查询
JMP KEY5_SR
KEY6:
CJNE A,#0BBH,KEY7 ;6键查询
JMP KEY6_SR
KEY7:
CJNE A,#0EDH,KEY8 ;7键查询
JMP KEY7_SR
KEY8:
CJNE A,#0DDH,KEY9 ;8键查询
JMP KEY8_SR
KEY9:
CJNE A,#0BDH,KEYA ;9键查询
JMP KEY9_SR
KEYA:
CJNE A,#077H,KEYB ;A键查询
JMP KEYA_SR
KEYB:
CJNE A,#07BH,KEYC ;B键查询
JMP KEYB_SR
KEYC:
CJNE A,#07DH,KEYD ;C键查询
JMP KEYC_SR
KEYD:
CJNE A,#07EH,KEYE ;D键查询
JMP KEYD_SR
KEYE:
CJNE A,#0EEH,KEYF ;E键查询
JMP KEYE_SR
KEYF:
CJNE A,#0BEH,KEY_SER_END ;F键查询
JMP KEYF_SR
KEY0_SR:MOV R7,#0 ;译码,将码值存放在R7中
JMP KEY_SER_END
KEY1_SR:MOV R7,#1
JMP KEY_SER_END
KEY2_SR:MOV R7,#2
JMP KEY_SER_END
KEY3_SR:MOV R7,#3
JMP KEY_SER_END
KEY4_SR:MOV R7,#4
JMP KEY_SER_END
KEY5_SR:MOV R7,#5
JMP KEY_SER_END
KEY6_SR:MOV R7,#6
JMP KEY_SER_END
KEY7_SR:MOV R7,#7
JMP KEY_SER_END
KEY8_SR:MOV R7,#8
JMP KEY_SER_END
KEY9_SR:MOV R7,#9
JMP KEY_SER_END
KEYA_SR:MOV R7,#0AH
JMP KEY_SER_END
KEYB_SR:MOV R7,#0BH
JMP KEY_SER_END
KEYC_SR:MOV R7,#0CH
JMP KEY_SER_END
KEYD_SR:MOV R7,#0DH
JMP KEY_SER_END
KEYE_SR:MOV R7,#0EH
JMP KEY_SER_END
KEYF_SR:MOV R7,#0FH
JMP KEY_SER_END
KEY_SER_END:
RET
;===================================
;共阳数码管码表
DISCODE:
DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H
; 0 1 2 3 4 5 6 7 8 9
DB 88H,83H,0C6H,0A1H,86H,08EH,0BFH,0FFH,0F7H
; A B C D E F - 消隐 _
;===================================
;扫描键码
KEYCODE:
DB 0DEH,0E7H,0D7H,0B7H,0EBH,0DBH,0BBH
; 0 1 2 3 4 5 6
DB 0EDH,0DDH,0BDH,77H,7BH,07DH,07EH,0EEH,0BEH
; 7 8 9 A B C D * #
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -