📄 keyscan.asm
字号:
;Keyscan.asm
;键盘扫描及数码管显示实验
;****************根据查看端口资源修改下列符号值*******************
IOY0 EQU 9C00H ;片选IOY0对应的端口始地址
;*****************************************************************
MY8255_A EQU IOY0+00H*4 ;8255的A口地址
MY8255_B EQU IOY0+01H*4 ;8255的B口地址
MY8255_C EQU IOY0+02H*4 ;8255的C口地址
MY8255_MODE EQU IOY0+03H*4 ;8255的控制寄存器地址
STACK1 SEGMENT STACK
DW 256 DUP(?)
STACK1 ENDS
DATA SEGMENT
DTABLE DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,77H,7CH,39H,5EH,79H,71H
DATA ENDS ;键值表,0~F对应的7段数码管的段位值
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START: MOV AX,DATA
MOV DS,AX
MOV SI,3000H ;建立缓冲区,存放要显示的键值
MOV AL,00H ;先初始化键值为0
MOV [SI],AL
MOV [SI+1],AL
MOV [SI+2],AL
MOV [SI+3],AL
MOV [SI+4],AL
MOV [SI+5],AL
MOV DI,3005H
MOV DX,MY8255_MODE ;初始化8255工作方式
MOV AL,81H ;方式0,A口、B口输出,C口低4位输入
OUT DX,AL
BEGIN: CALL DIS ;显示刷新
CALL CLEAR ;清屏
CALL CCSCAN ;扫描按键
JNZ GETKEY1 ;有键按下则跳置GETKEY1
MOV AH,1 ;判断PC键盘是否有按键按下
INT 16H
JZ BEGIN ;无按键则跳回继续循环,有则退出
QUIT: MOV AX,4C00H ;返回到DOS
INT 21H
GETKEY1:CALL DIS ;显示刷新
CALL DALLY
CALL DALLY
CALL CLEAR ;清屏
CALL CCSCAN ;再次扫描按键
JNZ GETKEY2 ;有键按下则跳置GETKEY2
JMP BEGIN ;否则跳回开始继续循环
GETKEY2:MOV CH,0FEH
MOV CL,00H ;设置当前检测的是第几列
COLUM: MOV AL,CH ;选取一列,将X1~X4中一个置0
MOV DX,MY8255_A
OUT DX,AL
MOV DX,MY8255_C ;读Y1~Y4,用于判断是哪一行按键闭合
IN AL,DX
L1: TEST AL,01H ;是否为第1行
JNZ L2 ;不是则继续判断
MOV AL,00H ;设置第1行第1列的对应的键值
JMP KCODE
L2: TEST AL,02H ;是否为第2行
JNZ L3 ;不是则继续判断
MOV AL,04H ;设置第2行第1列的对应的键值
JMP KCODE
L3: TEST AL,04H ;是否为第3行
JNZ L4 ;不是则继续判断
MOV AL,08H ;设置第3行第1列的对应的键值
JMP KCODE
L4: TEST AL,08H ;是否为第4行
JNZ NEXT ;不是则继续判断
MOV AL,0CH ;设置第4行第1列的对应的键值
KCODE: ADD AL,CL ;将第1列的值加上当前列数,确定按键值
CALL PUTBUF ;保存按键值
PUSH AX
KON: CALL DIS ;显示刷新
CALL CLEAR ;清屏
CALL CCSCAN ;扫描按键,判断按键是否弹起
JNZ KON ;未弹起则继续循环等待弹起
POP AX
NEXT: INC CL ;当前检测的列数递增
MOV AL,CH
TEST AL,08H ;检测是否扫描到第4列
JZ KERR ;是则跳回到开始处
ROL AL,1 ;没检测到第4列则准备检测下一列
MOV CH,AL
JMP COLUM
KERR: JMP BEGIN
CCSCAN PROC NEAR ;扫描是否有按键闭合子程序
MOV AL,00H
MOV DX,MY8255_A ;将4列全选通,X1~X4置0
OUT DX,AL
MOV DX,MY8255_C
IN AL,DX ;读Y1~Y4
NOT AL
AND AL,0FH ;取出Y1~Y4的反值
RET
CCSCAN ENDP
CLEAR PROC NEAR ;清除数码管显示子程序
MOV DX,MY8255_B ;段位置0即可清除数码管显示
MOV AL,00H
OUT DX,AL
RET
CLEAR ENDP
DIS PROC NEAR ;显示键值子程序
PUSH AX ;以缓冲区存放的键值为键值表偏移找到键值并显示
MOV SI,3000H
MOV DL,0DFH
MOV AL,DL
AGAIN: PUSH DX
MOV DX,MY8255_A
OUT DX,AL ;设置X1~X4,选通一个数码管
MOV AL,[SI] ;取出缓冲区中存放键值
MOV BX,OFFSET DTABLE
AND AX,00FFH
ADD BX,AX
MOV AL,[BX] ;将键值作为偏移和键值基地址相加得到相应的键值
MOV DX,MY8255_B
OUT DX,AL ;写入数码管A~Dp
CALL DALLY
INC SI ;取下一个键值
POP DX
MOV AL,DL
TEST AL,01H ;判断是否显示完?
JZ OUT1 ;显示完,返回
ROR AL,1
MOV DL,AL
JMP AGAIN ;未显示完,跳回继续
OUT1: POP AX
RET
DIS ENDP
PUTBUF PROC NEAR ;保存键值子程序
MOV SI,DI
MOV [SI],AL
DEC DI
CMP DI,2FFFH
JNZ GOBACK
MOV DI,3005H
GOBACK: RET
PUTBUF ENDP
DALLY PROC NEAR ;软件延时子程序
PUSH CX
MOV CX,00FFH
D1: MOV AX,00FFH
D2: DEC AX
JNZ D2
LOOP D1
POP CX
RET
DALLY ENDP
CODE ENDS
END START
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -