概述
在单片机系统中,当输入按键较多时,在硬件设计和软件编程之间总存在着矛盾。对于不同的单片机系统需要进行专用的键盘硬件设计和编程调试,通用性差,使项目开发复杂化。标准pc键盘在工艺与技术上都已相当成熟,而且工作稳定,价格低廉。本设计实现了一个接口模块,它将标准pc键盘发出的位置扫描码,变换为标准的ascii码和oem扫描码或windows虚拟键代码,再以并行或串行方式传送给上位单片机。
接口模块的特点
该模块在pc键盘与上位单片机之间起转换作用,它屏蔽了与pc键盘进行数据和命令交互的复杂过程,大大简化了上位单片机系统的输入设计;它实现了类似dos操作系统中键盘中断服务程序的功能,使设计人员只需关心接收按键的结果,并可使用标准的键盘编码进行编程;它要求上位单片机通过8位并行接口与其相接,对于不能提供并行接口的系统,可使用spi兼容的同步串行接口与其相接,特别是对于那些希望占用单片机的系统资源少而需要扩展的键数较多、仪器整体需要美观大方的应用场合,其性能价格比更具优势。该模块与单片机系统的连接关系如图1所示,在图中也给出与上位单片机相接的20脚接插件的信号定义。
计算机中标准pc机键盘的工作原理
![](http://www.picavr.com/upload/2008_01/080130180470342.jpg)
图2 键盘接口时序(a) 键盘发送时序;(b) 键盘接收时序
标准键盘与主机的通信是双向的,并采用11位的串行异步通信格式,这11位数据包括:起始位0、8位数据位(lsb在先)、奇校验位p、停止位1。图2(a)给出了键盘发送时序。数据(kb_dat)在时钟(kb_clk)的上升沿改变,下降沿时有效,可被主机读取。图2(b)给出键盘接收时序。主机发送前,先将kb_clk拉低,以抑制键盘发送,再将kb_dat拉低发送起始位,然后释放kb_clk线,键盘接管kb_clk并产生时钟信号,主机在kb_clk信号同步下发送其他位。
标准pc键盘接口模块的工作原理
基本工作原理概述
该模块的原理框图如图3所示。pc键盘与该模块通过专用插座相连,数据kb_dat接到at89c2051的p3.0引脚,时钟kb_clk接到引脚。在pc键盘有键按下时,kb_clk信号会引起at89c2051的连续中断,通过定时器t0与外中断的协同工作,可将pc键盘发出的位置扫描码序列接收至缓冲区中。然后,在主程序中将位置扫描码解码、查表换算,再编码成一字节的windows虚拟键代码或两字节的oem扫描码与ascii码,并存入系统中fifo栈。在上位单片机可以接收新键值时,将fifo栈中编码数据以并行或串行方式传送给上位单片机。 为了能更清楚地指示系统当前的工作状态,在硬件上加装了电源、正在解码、fifo栈溢出、码值准备好等指示灯。
中断解码的工作原理
由于键盘的按键输入是随机的,为了能实时地响应,在程序中使用定时器t0中断和中断协同工作,将位置扫描码序列恢复至键盘接收缓冲区中。中断服务程序用来将码值的一位移入缓冲区中,t0溢出的中断服务程序主要用来判断一次按键所发出的码是否已全部接收。系统设置t0的定时间隔为5ms,并在系统启动后就开始定时。由于在正常接收每个按键的码值序列过程中,键盘发送的每位数据间隔不会大于5ms,因此在每次中断服务中,首先要判断t0是否溢出过,若曾经溢出,则认为该次中断是一次新码值接收的开始,需将位计数器清零,否则只需移入一位数据即可,然后重新启动定时器,退出中断服务程序。在新按键码值序列接收完成后,设置blndatavalid标志,以通知主程序。
主程序的工作原理
主程序主要有四个任务:①将键盘接收缓冲区的位置扫描码通过查表等算法换成统一编码的一个字节windows虚拟键代码或两个字节的oem扫描码与ascii码;②根据系统中caps lock键、num lock键及scroll lock键的状态信息控制键盘上三个指示灯的亮灭;③系统中设立的fifo栈的维护;④与上位单片机码值传送的握手交互过程。主程序的流程图如图4所示。
在主程序中检测到blndatavalid标志后,即说明在键盘接收缓冲区中已接收到一个新的位置扫描码序列,程序根据这个序列的不同特点做不同的处理,最后再根据硬件跳线的设置得到相应按键的windows虚拟键代码或ascii码与oem扫描码,图4中的跳线接至“w”位时,编码为windows虚拟键代码。虚拟键代码是windows系统中引入的一组按键编码常量,每一个按键都有惟一的码值与之对应。ascii码与oem扫描码则是在dos系统定义的,但在windows系统中沿用的按键码值定义,每一个按键都有两个码值与之对应,对于功能键,例如f1、home、up等,只存在oem扫描码,其ascii码为0,参见表1。
fifo栈是程序中设置的发送缓冲区,它是按“先进先出”原则建立的32字节循环队列,有一个队列头指针和一个队列尾指针。进队列时,编码数据进入由队列尾指针所指单元,同时队列尾指针增量,指向下一个单元,当数据不断进入队列,使尾指针指向队列末端时,尾指针循环重新绕回队列始端;出队列时,编码数据从队列头指针所指的单元取出,同时队列头指针增量,指向下一个单元,在头指针指向队列末端时,也要重新绕回队列始端,但头指针始终不能“超过”尾指针。如果按键速度快于上位单片机接收码值的速度,有可能尾指针绕回后与头指针再次相等,这时表明队列已满,不能再存入数据,如果此时再有键按下,那么栈溢出指示灯将点亮。 在系统中设立了三个标志分别对应于caps lock键、num lock键及scroll lock键的状态,每次有这三个键按下时,程序都要翻转相应标志,然后向键盘发送edh命令,命令键盘对其上的三个led指示灯做相应激励。
在向上位单片机发送fifo栈首的码值之前要先检测ack信号状态以确定上位单片机是否已取走上次码值。若ack信号有效,则将码值锁存在p1口上,然后由p3.7产生模拟的时钟脉冲信号,一方面将8位并行码值置入串-并转换芯片(74ls165)中,另一方面将触发器(74ls74)置为1,使端变为0,为上位单片机提供码值准备好(ps_ready#)的状态信号,并点亮指示灯。在上位单片机中,可查询此状态信号也可利用此状态信号申请中断。上位单片机若采用并行接口方法,则发出读缓冲器信号(p_rd#)和片选信号(p_cs#),便可通过三态缓冲器(74ls244)取得键值;若采用串行接口方法,则需发出串行时钟(s_clk),从74ls165的串行数据端(s_dat)读回8位码值。在上位单片机读取完当前的键值后,ack信号将由握手逻辑自动置为有效,系统可通过检测ack信号的状态以发送下一个码值。
![](http://www.picavr.com/upload/2008_01/080130180470344.jpg)
图4 主程序流程图
实践证明应用该模块不但可大大地简化键盘输入电路及程序设计,而且在使用高级语言书写程序时更加方便。该模块可识别标准pc键盘上的所有按键,并能自动考虑shift、numlock及caplock键对编码的影响。对于dos系统中crtl+按键、alt+按键等组合键,该模块并未考虑,但相对上位的单片机系统而言,目前所提供的按键数量已足够用了。