廉价实用的8×8键盘

🏠 首页 《无线电》杂志 1993年 🔗 第3期 🔗 第27页 分类:无线电技术自学经验交流 🔗 黄迎胜 🔗

(黄迎胜)键盘是单片机最简单且最常用的输入设备,操作员通过键盘输入数据或命令,实现简单的人机通信。

键盘的组成方法很多,对于键较多的键盘通常都是利用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的接口少,电路、程序简单有实用价值。

一、硬件分析

硬件逻辑图如图1所示,让我们对照8031读外部RAM单元的波形图(图2),分析一下它的工作原理。

图1
图1 🔍原图 (1067×931)
图2
图2 🔍原图 (949×436)

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
图3 🔍原图 (471×137)

方法为判别到键盘上有键闭合后,延迟一段时间再判别键盘的状态,若仍有键闭合,则认为键盘上有一个键处于稳定的闭合期,否则认为是键的抖动。

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。

图4
图4 🔍原图 (480×536)

程序清单如下列,位地址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