目的
1.掌握I/O芯片编程应用
2.掌握矩阵键盘编码设计技术
要求
- 用扫描法读取键值显示。
- 用反转法读取键值显示。
代码
这里用了三种方法,其实大同小异可以读一下程序作为参考
第一种
DOUT EQU 0A000H ; 数码管控制口
KEY_RAS EQU 8000H ; 行线控制口
KEY_CAS EQU 9000H ; 列线控制口
data segment
LEDMAP db 3fh, 06h, 5bh, 4fh, 66h, 6dh, 7dh, 07h ; 八段管显示码
db 7fh, 6fh, 77h, 7ch, 39h, 5eh, 79h, 71h
KeyTable db 0ch, 0dh, 0eh, 0fh ; 键码定义
db 08h, 09h, 0ah, 0bh
db 04h, 05h, 06h, 07h
db 00h, 01h, 02h, 03h
data ends
code segment
assume cs:code, ds:data
Start proc near
MOV AX, data
MOV DS, AX
MOV DX,DOUT
MOV AL, 0
OUT DX, AL
MLoop: CALL TestKey ; 检查有键入?
CMP AL, 0
JZ MLoop ; 无键入, 继续查询
CALL Delay ; 消抖动
CALL GetKey ; 读入键码 修改设置
CMP AL, 0FFH
JZ MLoop
MOV BX, offset LEDMAP
XLAT
MOV DX, DOUT
OUT DX, AL
JMP MLoop
TestKey proc near ;无键按下,返回为0
MOV DX, KEY_RAS
MOV AL, 0
OUT DX, AL ; 输出线置为0
MOV DX, KEY_CAS
IN AL, DX ; 读入键状态
NOT AL
AND AL, 0FH ; 高四位不用
RET
TestKey endp
GetKey proc near
PUSH BX
PUSH CX
PUSH DX
MOV CH, 00000001B ; R3R2R1R0
MOV BH, 0 ; 列计数
MOV BL, 0 ; 行计数
KLoop: MOV DX, KEY_RAS ; 行线
MOV AL, CH ; 找出键所在行
NOT AL
OUT DX, AL
SHL CH, 1
MOV DX, KEY_CAS ; 列线
IN AL, DX
NOT AL
AND AL, 0FH ; 取低4位
JNE KNEXT ; 该列有键入
INC BL
CMP BL, 4
JNZ KLoop
MOV AL,0FFH ; 没有键按下, 返回 0ffh
JMP Exit2
KNEXT: TEST AL, 1
JNZ Exit1
SHR AL, 1
INC BH
CMP BH, 4
JNZ KNEXT
JMP Exit2
Exit1: MOV CL, 2
SHL BL, CL
ADD BL, BH ;键值 = 行X 4 +列
MOV AL, BL
;MOV BX, offset KeyTable
;XLAT
Exit2: POP DX
POP CX
POP BX
RET
GetKey endp
Delay proc near
PUSH AX ; 延时子程序
PUSH CX
MOV AL, 10H
MOV CX, AX
LOOP $
POP CX
POP AX
RET
Delay endp
Start endp
code ends
end Start
第二种
DOUT EQU 0A000H ; 数码管控制口
KEY_RAS EQU 8000H ; 行线控制口
KEY_CAS EQU 9000H ; 列线控制口
data segment
LEDMAP db 3fh, 06h, 5bh, 4fh, 66h, 6dh, 7dh, 07h ; 八段管显示码
db 7fh, 6fh, 77h, 7ch, 39h, 5eh, 79h, 71h
KeyTable db 0ch, 0dh, 0eh, 0fh ; 键码定义
db 08h, 09h, 0ah, 0bh
db 04h, 05h, 06h, 07h
db 00h, 01h, 02h, 03h
data ends
code segment
assume cs:code, ds:data
Start proc near
MOV AX, data
MOV DS, AX
MOV DX,DOUT
MOV AL, 0
OUT DX, AL
MLoop: CALL TestKey ; 检查有键入?
CMP AL, 0
JZ MLoop ; 无键入, 继续查询
CALL Delay ; 消抖动
CALL GetKey ; 读入键码 修改设置
CMP AL, 0FFH
JZ MLoop
MOV BX, offset LEDMAP
XLAT
MOV DX, DOUT
OUT DX, AL
JMP MLoop
TestKey proc near ;无键按下,返回为0
MOV DX, KEY_RAS
MOV AL, 0
OUT DX, AL ; 输出线置为0
MOV DX, KEY_CAS
IN AL, DX ; 读入键状态
NOT AL
AND AL, 0FH ; 高四位不用
RET
TestKey endp
GetKey proc near
PUSH BX
PUSH CX
PUSH DX
MOV CH, 00000001B ; C3C2C1C0
MOV BH, 0 ; 列计数
MOV BL, 0 ; 行计数
KLoop: MOV DX, KEY_CAS ; 列线
MOV AL, CH ; 找出键所在列
NOT AL
OUT DX, AL
SHL CH, 1
MOV DX, KEY_RAS ; 行线
IN AL, DX
NOT AL
AND AL, 0FH ; 取低4位
JNE KNEXT ; 该列有键入
INC BH
CMP BH, 4
JNZ KLoop
MOV AL,0FFH ; 没有键按下, 返回 0ffh
JMP Exit2
KNEXT:
MOV CH, 00000001B ; R3R2R1R0
JNE KLoop1
KLoop1:
MOV DX, KEY_RAS ; 行线
MOV AL, CH ; 找出键所在行
NOT AL
OUT DX, AL
SHL CH, 1
MOV DX, KEY_CAS ; 列线
IN AL, DX
NOT AL
AND AL, 0FH ; 取低4位
JNE Exit1 ; 该列有键入
INC BL
CMP BL, 4
JNZ KLoop1
MOV AL,0FFH ; 没有键按下, 返回 0ffh
JMP Exit2
Exit1: MOV CL, 2
SHL BL, CL
ADD BL, BH ;键值 = 行X 4 +列
MOV AL, BL
;MOV BX, offset KeyTable
;XLAT
Exit2: POP DX
POP CX
POP BX
RET
GetKey endp
Delay proc near
PUSH AX ; 延时子程序
PUSH CX
MOV AL, 10H
MOV CX, AX
LOOP $
POP CX
POP AX
RET
Delay endp
Start endp
code ends
end Start
第三种
DOUT EQU 0A000H ; 数码管控制口
KEY_RAS EQU 8000H ; 行线控制口
KEY_CAS EQU 9000H ; 列线控制口
data segment
LEDMAP db 3fh, 06h, 5bh, 4fh, 66h, 6dh, 7dh, 07h ; 八段管显示码
db 7fh, 6fh, 77h, 7ch, 39h, 5eh, 79h, 71h
KeyTable db 0ch, 0dh, 0eh, 0fh ; 键码定义
db 08h, 09h, 0ah, 0bh
db 04h, 05h, 06h, 07h
db 00h, 01h, 02h, 03h
data ends
code segment
assume cs:code, ds:data
Start proc near
MOV AX, data
MOV DS, AX
MOV DX,DOUT
MOV AL, 0
OUT DX, AL
MLoop: CALL TestKey ; 检查有键入?
CMP AL, 0
JZ MLoop ; 无键入, 继续查询
CALL Delay ; 消抖动
CALL GetKey ; 读入键码 修改设置
CMP AL, 0FFH
JZ MLoop
MOV BX, offset LEDMAP
XLAT
MOV DX, DOUT
OUT DX, AL
JMP MLoop
TestKey proc near ;无键按下,返回为0
MOV DX, KEY_RAS
MOV AL, 0
OUT DX, AL ; 输出线置为0
MOV DX, KEY_CAS
IN AL, DX ; 读入键状态
NOT AL
AND AL, 0FH ; 高四位不用
RET
TestKey endp
GetKey proc near
PUSH BX
PUSH CX
PUSH DX
MOV BH, 0 ; 列计数
MOV BL, 0 ; 行计数
loop1:
MOV DX, KEY_RAS
MOV AL, 0
OUT DX, AL ; 输出线置为0
MOV DX, KEY_CAS
IN AL, DX ; 读入键状态
NOT AL
AND AL, 0FH ; 高四位不用
cmp AL,0
jnz test1
MOV AL,0FFH
jmp exit2
test1:
SHR al,1
inc BH
cmp al,0
jnz test1
dec BH
loop2:
MOV DX, KEY_CAS
MOV AL, 0
OUT DX, AL ; 输出线置为0
MOV DX, KEY_RAS
IN AL, DX ; 读入键状态
NOT AL
AND AL, 0FH ; 高四位不用
test2:
SHR al,1
INC BL
cmp al,0
jnz test2
dec BL
Exit1: MOV CL, 2
SHL BL, CL
ADD BL, BH ;键值 = 行X 4 +列
MOV AL, BL
;MOV BX, offset KeyTable
;XLAT
Exit2: POP DX
POP CX
POP BX
RET
GetKey endp
Delay proc near
PUSH AX ; 延时子程序
PUSH CX
MOV AL, 10H
MOV CX, AX
LOOP $
POP CX
POP AX
RET
Delay endp
Start endp
code ends
end Start
小结
这里面的第一种其实只是要求一,但是可以理解一下思路,第二种呢就是第一种的叠加,但是效率很低,要扫描16次,第三种方法是从同学那里学到的,确实简单只需要扫描一次,之后自己写了一下,也不难,现在越来越发现算法的重要性,害
本文章6.10前不允许抄袭转载,不允许当做接口作业使用