扩展你的电脑接口
小巧的键盘练习器
PS/2键盘接口应用实例

🏠 首页 《无线电》杂志 2004年 🔗 第5期 🔗 第30页 分类:电脑与单片机 🔗 温正伟 🔗

电脑键盘和鼠标不但是人们控制电脑的好帮手,也是我们日常工作生活的好伙伴,它们通过PS/2接口与电脑连接, 主机后面的PS/2插座和PS/2设备的连接器插头如图1所示。本期我们以制作一个小巧的键盘练习器为实例来了解PS/2键盘、鼠标接口的相关知识和利用方法。实例制作是用一个AT89C51的单片机连接PS/2键盘接口和一个16x2的液晶显示屏,当敲击键盘时,字母就可以显示在液晶显示屏上。这个实例能启发你如何利用单片机来实现对PS/2接口的控制。读者还可以把实例中提供的源码修改到其他PS/2键盘接口的制作项目中,实例中提供的16x2字符型的液晶显示屏的驱动函数实例也是可以直接应用的。图2是这个实例制作的实物图。

图1
图1 🔍原图 (518×302)
图2
图2 🔍原图 (567×451)

电路原理

实例的电路原理很简单。附表是元件列表,实例主电路的实物图如图3所示,电原理图如图4所示。主电路板中的AT89C51单片机(可以用AT89C52/S51/S52直接替换,如用AT89C2051/4051则要更改程序中相应的引脚定义)组成了51最小化系统、液晶显示屏用到了SMC1602A(16x2字符)。键盘通过PS/2六孔插座和主电路板相连接,液晶显示屏可用排线与主电路板相连。PS/2设备的连接器使用mini-DIN连接器,该连接器只有6根引线,其中有两根是保留不用的,起作用的只有4根,引脚定义见图5,V\(_{CC}\)是+5V,GND是地,DATA是数据线,CLK是时钟线。DATA和CLK都是可双向通信的I/O线,也就是说通过这两根线,既可以把主机的数据发到PS/2设备,又可以把设备的数据发向主机。至于液晶显示屏的引脚定义和相关资料可到网站www.sunman.com.cn上查找。

图4
图4 🔍原图 (850×327)
图3
图3 🔍原图 (567×452)
图20
图20 🔍原图 (850×570)
图21
图21 🔍原图 (425×168)

了解PS/2连接器的引脚定义后,就可以知道应该如何把它连接到AT89C51最小化单片机系统中去。从PS/2键盘协议可知(请看后文的说明)当键盘有键被按下时,CLK线会以一定的频率发出一串方波,也就是时钟信号,在这些时钟信号处于低电平时,DATA线会以一定的格式输出数据,这些数据就反映了所按的是什么键了。因此我们可以把CLK线连接到AT89C51单片机的P3.3外部中断1上,将DATA线连接到P3.4I/O引脚上,当有时钟信号到来时,低电平就会产生外部中断,这时就可以读取DATA线上的值,而单片机就可以取得按键值了。取得键值后经单片机的转换处理经P1和P2I/O口输出并行数据到液晶显示屏显示相应的字符。大家在制作时应注意把AT89C51的接上+5V的V\(_{CC}\),这样才能运行芯片内的程序。

程序编写

要想单片机按上述的电路时序工作自然就要求编写相应的单片机程序。本实例中提供的源码是C语言的源码。程序中大致分为3个模块:中断数据采集模块、键值查表模块和液晶显示驱动模块。单片机外部中断程序的作用就是当PS/2键盘有按键时,CLK线有时钟信息传入单片机外部中断,在时钟的下沿触发中断,中断程序工作,采集DATA线上的数据。当采集完一个帧数据后,程序转向键值查表程序,把采集来的键盘扫描码和PS/2键盘扫描码集的数据表相比较,查找出对应键值的ASCII码,最后把得出的ASCII码传送到液晶显示模块由相关的函数驱动液晶屏显示出字符。在数据采集和编程转换中要用到PS/2键盘的通信协议和键盘编码的知识。下面就对其进行简单的介绍。

PS/2键盘接口通信协议

PS/2接口多被应用在电脑的键盘和鼠标上,虽然现在有USB接口的键盘和鼠标,但可以肯定稍后2年内PS/2仍会是键盘和鼠标的主流接口。PS/2键盘和鼠标的基本数据传输方式是一样的,限于篇幅本文主要讲述PS/2键盘。在PS/2出现之前,AT式PC机上的键盘大多是使用5针的DIN连接器的AT键盘,PS/2则使用了更小的6针mini-DIN连接器,这两种连接器除外形外,没有太多的不同之处,两种键盘之间只要使用图6所示的转接线就可以相互换用,也就是说如果你只有一个老式的AT键盘,只需要一根转接线就可以使用于带PS/2接口的主机上。在上面提到的PS/2引脚定义中,PS/2设备的+5V电源将由主机提供(在本实例中则是连接到最小化电路板上的电源),DATA数据线和CLK时钟线是集电极开路的,因此在接口电路上会有上拉电阻,使它在无数据时保持高电平。那键盘和主机通信的具体时序又是如何的呢?

图7是设备向键盘发送数据时PS/2接口的时序图。在无击键发生时,DATA和CLK一直处于高电平状态,当有键被按下时,键盘先是检查CLK线,看它是否是处在高电平,如果是处在低电平说明主机无空闲接收数据,这时键盘将会缓冲数据(不同的PS/2设备有不同的缓冲字节,键盘一般为16字节,鼠标只有一个字节)直到主机空闲CLK重新被拉高,键盘获得总线权,这时键盘产生时钟信号在CLK线上输出,同时每一个时钟周期在DATA线上输出一位数据。第1位为起始位为0;第2~9位为一个八位二进制数据由低位到高位依次输出;第10位为奇校验位,用来错误检测,如果数据位中包含偶数个1校验位就会置1,如果数据位中包含奇数个1校验位就会置0,数据位中1的个数加上校验位总是奇数(这就是奇校验);第11位为停止位,表明一帧数据已发送完成,这时CLK也停止了时钟信号的输出,电平拉回到高位。键盘向主机发送数据时每帧数据有11位,产生11个时钟,在编程时主机可以在时钟信号变为低电平时(或在下降沿)开始读取DATA线上的数据。时钟的频率最高为33kHz,一般大多数都会使用10~20kHz,在编写程序时这个是值得注意的,如果设备发出的时钟频率为15kHz时,那么在每个时钟周期的低电平时间约为40礢,这就要求你的程序在读取一位数据的时间不得超出40礢。还有一点要注意的是键盘每送出一帧数据后都不需要主机发送“接收完成”的回应信号,也就是说无论主机是否接收到当前的数据,键盘都会发送下一个要发送的数据。

图8是主机向键盘发送数据时的时序图,PS/2接口是收还是发数据,时钟信号总是由设备所产生。主机要发送数据到键盘时,要先把DATA和CLK线设置成“请求发送”状态,做法是至少将CLK线拉低100礢,接着拉低DATA线,释放CLK线,主机等待键盘产生时钟信号,在第1个时钟周期的低电平起主机发送数据,由低位到高位依次发送,并发送奇校验位,在第11个时钟周期DATA线被释放,在第12个周期里,键盘会发出一个时钟周期的ACK信号(DATA被拉低)以通知主机已成功接收到数据,主机可以根据这个判断键盘是否收到数据。主机发送数据到PS/2设备的数据帧就包括了12位,设备应该在不超过10ms的间隔内就要检查CLK线是否被拉低,当被拉低时设备将开始产生时钟信号,并且时钟脉冲的上升沿输入8个数据位和1个停止位并锁存,而主机是在时钟线为低时发送数据,这和键盘发送数据到主机是相反的。在主机把停止位发送后,设备要应答已接收到数据就把数据线拉低并产生最后一个时钟脉冲,如果主机在第11个时钟脉冲后不释放数据线,设备将继续产生时钟脉冲直到数据线被释放,然后设备将产生一个错误。另外主机可以在第11个时钟前中止当前数据的传送,做法是下拉时钟线至少100礢。PS/2键盘通信协议也适用于PS/2的鼠标。

键盘的编码和软件实现

如果你拆装过键盘,就会发现键盘内安装了一个大型的按键矩阵,图9就是常用的一种键盘构造。按键矩阵是用两片导电塑料做成,它们是由安装在电路板上的键盘编码器(编码芯片)来监视其状态的,编码器会监视在一个时刻内有什么键被按下、放开或主机发来了信号等。图9所示的就是直接把编码芯片固化在电路板上,芯片的作用就是把按键矩阵的状态根据扫描码集对其进行编码,并把编码后的数据传送到DATA和CLK线上,同时也处理主机送来的数据。主机内的控制器则使用8042芯片,现在也有很多兼容的编码器芯片如8049、HT82K628A、EM83050H,键盘控制器多被整合到主机板的芯片组中去。

扫描码根据不同的事件可以分为通码和断码。通码就是指键被按下时所要发送的扫描码,断码则是键被放开时所要发送的扫描码。扫描码集对应所要表示的ASCII码都是没有规律可寻的,不能用一个简单的计算公式根据按键的扫描码得出所按的是什么键,一定要通过查表,本期配刊光盘的“本期程序”文件夹中有现在最常用第二套扫描码集,现在出售的键盘都会支持它。

那么如何知道按下一个或多个键时所产生的扫描码值呢?例如按下了左SHIFT+A键时,这时键盘会发送什么样扫描码呢?先来说说整个击键的过程,先按下左SHIFT键,再按下A键,释放A键,释放左SHIFT键,这些时间段内分别产生了左SHIFT的通码(12H),A的通码(1CH),A的断码(F0H,1CH),SHIFT断码(F0H,12H),查表后可以得出产生了12H、1CH、F0H、1CH、F0H、12H这一连串的扫描码,这些数据都是以上面所说的PS/2通信协议从键盘发向主机。用单片机解码时,在程序中可以根据每个断码前一字节为FOH去判断当前的键是否释放,同样SHIFT、CTRL等功能键都可以在程序中用标志位去进行处理,具体的做法可以参考本期配刊光盘中所附带的单片机C51源码。

如果你还没有读完下面一段就迫不及待地照上面的电路制作了,你就会发现当按NumLocK或CapsLock键时,并不像把键盘接入电脑主机那样会点亮相应的状态指示灯。这是因为在实例所提供的程序中并没有向键盘发送过任何的命令字。键盘的命令信息可以参看http://panda.cs.ndsu.nodak.edu/~achapwes/PICmicro/keyboard/atkeyboard.html(英文)。要注意的是每次从主机发送命令字节到键盘,键盘都会返回一个0xFA字节回应主机已收到命令,但Resend和Echo命令的回应除外。主机在发送下一个字节给键盘之前要先等待键盘应答字节,如在一段时间内没有收到可以判断为通信超时。键盘回应任何命令后会清除自己的输出缓冲区。本文所附带的实例源码中,单片机对键盘扫描码转换的方式先去掉断码,保留通码,用通码去查表。

关于本实例更多的相关资料和更新版本的源码请参与http://bbs.cdle.net的论坛讨论。与本实例相关的源程序、键盘扫描码集及命令字见本期配刊光盘的“本期程序”文件夹。

(温正伟)