微机键盘以其稳定性好、使用方便、价格便宜等优点,可有效地应用在输入量大、要求复杂的仪器仪表中。现存的计算机键盘种类很多,但基本原理和接口规范是一样的。IBM-PC键盘的核心器件是Intel公司的单片机8049。单片机采用行列扫描方法来监测是否有键按下。若有键按下,则转换为相应的扫描码,通过串行通讯线将其传给计算机,由主机接收并处理成扩展键盘码。
1 标准键盘工作原理
1.1 通信接口
键盘与计算机通过一个五芯接口插座座(PC/2接口为六芯)相接,各引脚定义分别是电源(VCC)、地(GND)、串行时钟线SCK和串行数据线SIO,还有一根线未用。两种键盘接口的插座外形图及各线定义如图1所示。
1.2 通信协议
标准键盘与计算机采用双向通信方式,键盘可以发送数据给计算机,计算机也可以发送命令给键盘。计算机有最高优先权,可以在任何时候发命令给键盘。通信协议是标准的串行异步通信格式,1位起始位,8位数据位(LSB在先),1位奇校验位P,最后是1位停止位。数据格式如图2所示。
当SIO和SCK同时为高电平时,键盘可以发数据给计算机。SCK可以用作清除发送线。如果计算机将SCK拉为低电平,键盘将不发送数据,而是将要发送的数据放到发送缓冲区中,直到SCK变为高电平才开始发送数据。如果计算机将SIO拉低,则键盘在检测到这一变化时,将接收来自计算机的命令。
图3(a)给出了键盘发送一个字节的时序。键盘先将SIO拉低,通知计算机准备接收数据。键盘在SCK的上升沿后改变数据,在下降沿时数据有效,可以被计算机读取。发送数据的时钟信号由键盘产生。有的文献介绍键盘时钟频率的典型值为20~30kHz,但实际上键盘的传送速原则不全在这个范围内。笔者曾做过测试,其中一只键盘的野外频率是12.4kHz。
图3(b)给出了键盘接收一个字节的时序。为了避免在同一时刻发送数据,建议计算机先将SCK拉低大约60μs 以上,以此通知键盘不要发数据。然后计算机将SIO拉低,表明发送数据开始,并释放SCK,由键盘接管SCK并产生时钟信号。计算机在此时钟信号的同步下发送数据。键盘接收数据是从检测到SIO变低开始的,然后在SCK下降沿读起始位,并在SCK的每个下降沿读取后缓数据。键盘在接收完校验位后,如果在下一个时钟周期检测到SIO处于空闲态(高电平),便会接受新数据并进行处理。在此期间,键盘将把SIO置成低电平,直到接受数据完成。如果收到校验位后,键盘检测到SIO没有处于空闲态,它将继续发送时钟信号直到SIO空闲。
1.3 键盘扫描码
一个基本按键的扫描码由3个字节组成,1个字节的接通扫描码和2个字节的断开扫描码。其中第一与第三个字节相同,中间字节是断开标志F0H。例如B键的接通扫描码是32H,断开扫描码是F0H32H。B键被按下时,32H被发送出去,如果一直按住不放,则键盘将以按键重复率不停地发送32H,直到该释放放,才发出断开扫描码F0H 32H.扫描码与按键折位置有关,与该键的ASCII码并无对应关系。键盘上还有部分扩展键(功能键和控制键等),这些键的扫描码由5个字节组成。与基本键的扫描码相比,接通扫描码与断开扫描码前各多了一个固定值字节E0H。例如Home键的接通扫描码是E0H 70H,熠工扫描码是E0H F0H 70H。还有两个特殊键,PrintScreen键的接通扫描码是E0H 12H E0H 7CH;断开扫描码是E0H F0H 7CH E0H F0H12H,PauseBreak键的接通扫描码是E1H 14H 77H E1H F0H 14H F0H 77H,无断开扫描码。
1.4 通信命令字
除了键盘可以向计算机发送按键的扫描码外,计算机还可以向键盘发送预定的命令字来对键盘功能进行设定。
1.4.1 计算机发往键盘的命令
EDH:设置状态指示灯。该命令用来控制键盘上3个指示灯NumLock、ScrollLock、CapLock的亮灭。EDH发出后,键盘将回应计算机一个收以应答信号FAH,然后等待计算机发送下一个字节,该字节决定各指示灯的状态。
Bit0控制ScrollLock;
Bit1控制NumLock;
Bit2控制CapLock;
Bit3~Bit7必须为0,否则键盘认为该字节是无效命令,将返回FEH,要求重发。
EEH:回送响应。该命令用于辅助诊断,要求键盘收到EEH后也回送EEH予以响应。
F0H:设置扫描码。键盘收到该命令后,将回送收到信号FAH,并等待下一命令字节,该字节的值01~03将决定键盘使用三种扫描码中的哪一种。
上电复位时,键盘默认扫描码类型是02,本文所举的例子皆为此类型扫描码。不同类型的扫描码与不同类型的微机相匹配。01类型扫描码由两字节组成,分别为接通扫描码和断开扫描码;03类型扫描码只有一个字节,为接通扫描码。
F3H:设置键盘重复速率,计算机发送该命令后,键盘将加送收到信号FAH,然后等待计算机的第二个字节,该字节决定按键的重复速率。
F4H:键盘使能。计算机发该命令给键盘后,将清除键盘发送缓冲区,重新使键盘工作,并返回收到信号FAH。
F5H:禁止键盘。计算机发该命令给键盘后,将使键盘复位,并禁止键盘扫描。键盘将返回收到信号FAH。
FEH:重发命令。键盘收到此命令后,将会把上次发送的最后一个字节重新发送。
FFH:复位键盘。此命令将键盘复位。若复位成功,键盘回送收到信号FAH和复位完成信号AAH。
1.4.2 键盘发往计算机的命令
00H:出错或缓冲区已满。
AAH:电源自检通过。BAT(基本保证测试)完成。
EEH:回送响应。
FAH:响应信号。键盘每当收到计算机的命令后,都会发此响应信号。
FEH:重发命令。计算机收到此命令后,将会把上次发送的最后一个命令字节重新发送。
FFH:出错或缓冲区已满。
2 键盘与单片机的接口电路及程序
采用Atmel89C51单片机与标准键盘接口电路如图4所示。口线P1.0和P1.1分别连接SCK和SIO,单片机的口线是上拉输出形式,可以和键盘的通信线直接相连,由软件控制口线产生收发时序。
应用程序合作Franklin C51编写。在程序中,单片机要用查询方式检测数据线状态。如果数据线变为低电平,说明键盘即将有数据发出,则调用读键盘子程序receive_data读取一个字节数据;若要发命令字给键盘,单片机则调用子程序send_data来完成。
单片机读取来自键盘数据的子程序如下,该程序接收一个字节数据存放在变量from_kb中,并将该值返回到主程序,校验位放在全局位变量p_bit中。
#include <reg51.h>
sbit sio=P1^1; /*数据线*/
sbit sck=P1^0; /*时钟线*/
sbit ACC_7=ACC^7;
sbit ACC_0=ACC^0;
bit p_bit; /*检验位*/
char receive_data(void)
{ char i;
char from_kb; /*放接收到的数据*/
while(sck);
while(!sck); /*放弃起始位*/
for(i=0;i<8;i++) /*读取数据字节*/
{ while(sck); /*下降沿读取数据*/
from_kb>>=1;
ACC=from_kb;
ACC_7=sio;
from_kb=ACC;
while(!sck);
}
while(sck);
p_bit=sio; /*读取校验位*/
while(!sck);
while(sck); /*略去读停止位*/
while(!(sck&sio)); /*等待时钟线与数据线都释放*/
return(from_kb);
}
下列程序是89C51单片机发送一个命令字节给键盘的子程序。要发送的命令字由程序传送,并存于变量to_kb中,该程序按照接口的时序通过口线将命令字节传送给键盘。
Void send_to_kb(char to_kb) using 1
{ char i;
ACC=to_kb;
p_bit=!P; /*对发送字节进行奇校验,校验结果放在p_bit中*/
sck=0; /*将时钟线拉低*/
for(i=0;i<60;i++); /*时钟线低电平保持60μs以上,以禁止键盘往外发数据*/
sio=0; /*通知键盘接受命令字节,同时也作为起始位*/
sck=1; /*释放时钟线,以在键盘发出的时钟信号同步下,发送命令字*/
for(i=0;i<8;i++) /*发送命令字节*/
{ while(sck);
while(!sck); /*上升沿发数据*/
ACC=to_kb;
sio=ACC_0;
to_kb>>=1;
}
while(sck);
while(!sck);
sio=p_bit; /*发送奇校验位*/
while(sck);
while(!sck);
sio=1; /*释放数据线*/
}
单片机的嵌入式应用中有些需要进行大量的文字输入、参数修改和数值设定等操作。通常的方法是在电路中设计键盘电路、键盘接口的按键程序,这不仅占用许多硬件资源,而且由于键扫描处理程序一般都很庞大,软件开销也很大。如果在仪器上预留一个标准键盘接口,改用微机键盘对仪器仪表进行操作,则不仅占用系统资源少,成本低廉,而且微机键盘的键资源特别丰富,也给操作带来极大方便。本方法在学校打铃微电脑定时控制器中被采用,使得时间调整和上百组打铃设置操作变得非常容易。