(黄迎胜)键盘是单片机最简单且最常用的输入设备,操作员通过键盘输入数据或命令,实现简单的人机通信。
键盘的组成方法很多,对于键较多的键盘通常都是利用8031的P1口或P3口组成矩阵方式。P1口和P3口被其它用途占用后,就得采用扩展芯片。这里介绍的是只利用8031的P0口和一片三态门电路(373或244),用指令MOVX A,@R0实现的8×8键盘。它妙在只用一条指令(MOVX A,@R0),前半周期用P0口输出存放在工作寄存器R0中的扫描信号,后半周期又用P0口读入键盘状态(存入累加器A中)。其特点是:键数多(加上P2口,可扩展成16×8键盘),占用CPU的接口少,电路、程序简单有实用价值。
一、硬件分析
P2口输出外部RAM单元的高8位地址(DPH或P2口锁存器内容送到P2口驱动器输出),当地址锁存允许信号ALE为高电平时,P0口输出的地址信息(来自R0或R1或DPL)有效,此地址信息其实是键盘的列扫描信息(如:扫描第一列时,地址信息为00000010B),ALE的下降沿将此信息打入外部地址锁存器IC3。接着,P0口变为输入方式,读信号RD—有效(负脉冲),若此时的P2.7为低电平,则IC2被选通,三态门处于导通状态,其输入口与输出口的内容相同。若此时键盘被扫描的列(如:列1)上无键闭合,则P0口全为低电平,若此列有键闭合(如键11),则P0上的内容为非全零(如 00001000B),被CPU读入累加器A。如果读信号RD—有效时,P2.7为高电平,则IC2没有被选通,其三态门处于浮空状态,不影响P0口与外部RAM间的数据传输。
图1中,电阻R1~R8的阻值选取要考虑到IC3的驱动能力,二极管VD1~VD8是当键盘同一行中,有二个或二个以上的键(如键0和键8)同时闭合时,防止低8位地址(如A0和A1)相互干扰而设置的。
二、软件分析
8031对键盘采用扫描方式,程序的设计要具有以下3个功能:
1.判别键盘上有无键闭合
参照图1,设扫描口A0~A7输出全为“1”,读键盘状态,若无键闭合,则P0口全为低电平;若有键闭合,则P0口就不全为零。
2.去除键的机械抖动
键每闭合一次,IC2相应的三态门输入口的电压都要经过图3所示的过程。其中t1和t3分别为键闭合和断开过程中的抖动期,抖动时间长短和开关的机械特性有关,一般为5~10ms之间;t2为稳定的闭合期;t0和t4为断开期。为了保证CPU对键的每一次闭合只作一次处理,必须去除抖动,在键的稳定闭合期读键的状态,并判别到键释放后再作下一个键输入处理。

方法为判别到键盘上有键闭合后,延迟一段时间再判别键盘的状态,若仍有键闭合,则认为键盘上有一个键处于稳定的闭合期,否则认为是键的抖动。
3.判别闭合键的键号
对键盘的列线进行扫描,扫描口A0~A7依次输出:
A7 A6 A5 A4 A3 A2 A1 A0
0 0 0 0 0 0 0 1
0 0 0 0 0 0 1 0
…… ……
1 0 0 0 0 0 0 0
相应地读P0口的状态,若P0口全为“0”,则列线为1的这一列上没有键闭合,否则这一列上有键闭合,闭合键的键号等于为高电平的行的行号乘以8加上为高电平的列的列号。例如:A0~A7为00000010时,读出P0口为00001000,则1列和3行相交的键处于闭合状态,闭合键的键号为:
N=列数×8+行数=1×8+3=11
8031对键盘采用定时扫描方式,利用定时器方式0,产生10ms的定时中断,CPU响应中断时对键盘进行扫描,以响应键输入请求,定时中断服务程序的设计方法是在内部RAM的位寻址区,设立去抖动标志KM和处理标志KP两个标志位,流程图如图4。

程序清单如下列,位地址0FH位为去抖动标志,0EH位为处理标志,处理后的键号存入21H单元。
9
ORG 0000H
AJMP MAIN
ORG 000BH ;转T0溢出中断处理
AJMP KEY
MAIN: MOV TL0,#18H;设置定时器初值
MOV TH0,#67H
SETB TR0 ;启动定时器
MOV IE, #82H;开放T0中断
HERE: AJMP HERE
KEY: PUSH PSW ;保护现场
PUSH ACC
PUSH R0
PUSH P2
MOV P2,# 80H;IC2的选通地址存入P2锁存器
MOV R0,#0FFH;置A0~A7都为“1”
MOVX A, @ R0
JNZ KEY1 ;若有闭合键,跳KEY1
MOV 20H,#00H ;置KM,KP都为零
AJMP RETU
KEY1: JB 0FH,KM1 ;若KM=1,跳KM1
SETB 0FH ;置KM=1
AJMP RETU
KM1: JNB 0EH,KP0 ;若KP=0,跳KP0
AJMP RETU
KP0: MOV 20H,#0C0H;置KP、KM都为“1”,
清除20H单元的低四位
SETB C ;扫描口初始化
CLR A
NEXTL:RLC A
JZ RETU ;若扫描结束,跳RETU
MOV R
MOVX A
JNZ FINDL ;若此列有闭合键,跳FINDL
INC 20H ;列数加1
MOV R
AJMP NEXTL
FINDL:MOV 21H,#00H ;清除21H单元
NEXTN ACC.0,FINDN;若此行有闭合键,
INC 21H ;行数加1 跳FINDN
RR A
AJMP NEXTN
FINDN:MOV R0,20H
CLR A
XCHD A,R0 ;列数送A
PUSH B ;保护B
MOV B,#08H
MUL AB ;列数乘以8,送A(列首键号)
POP B ;恢复B
ADD A,21H ;列首键号加行数(键号)
MOV 21H,A ;键号存入21H单元
RETU: MOV TL0, #18H;设置定时器初值
MOV TH0, #67H
POP P2 ;恢复现场
POP R0
POP ACC
POP PSW
RETI

