DIY编程器网

 找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 327|回复: 0
打印 上一主题 下一主题

单片机系统中PS/2键盘驱动程序设计

[复制链接]
跳转到指定楼层
楼主
发表于 2012-1-27 19:48:45 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

  
         
   







摘 要分析PS/2协议;介绍PS/2标准健盘的第二套扫描码和命令集,并给出在单片机系统中支持PS/2健盘的硬件连接方式和利用Keil C51语言实现的驱动程序设计及部分代码。该驱动程序可以方便地移植到其他单片机或嵌入式系统中。
关健词 PS/2协议 PS/2健盘 单片机 驱动程序
    在单片机系统中,经常使用的键盘都是专用键盘。这类键盘都是单独设计制作的,成本高,连线多,且可靠性不高。这些问题在那些要求键盘按键较多的应用系统中显得更加突出。与此相比,在 PC系统中广泛使用的PS/2键盘具有价格低、通用可靠,且使用的连线少(仅使用2根信号线)的特点,并可满足多数系统的要求。因此,在单片机系统中应用PS/2键盘是一种很好的选择。   
    本文在分析PS/2协议和PS/2键盘工作原理与特点的基础上,给出在AT89C51单片机上实现对PS/2键盘支持的硬件连接方法以及驱动程序的设计实现。
1  PS/2协议
    现在PC机广泛采用的PS/2接口为mini - DIN 6引脚的连接器。其引脚如图1所示。


740)this.width=740" border=undefined>
    PS/2设备有主从之分,主设备采用female插座,从设备采用male插座。现在广泛使用的PS/2键盘鼠标均工作在从设备方式下。PS/2接口的时钟与数据线都是集电
极开路结构的,必须外接上拉电阻。一般上拉电阻设置在主设备中。主从设备之间数据通信采用双向同步串行方式传输,时钟信号由从设备产生。
(1)从设备到主设备的通信
    当从设备向主设备发送数据时,首先会检查时钟线,以确认时钟线是否是高电平。如果是高电平,从设备就可以开始传输数据;否则,从设备要等待获得总线的控制权,才能开始传输数据。传输的每一帧由11位组成,发送时序及每一位的含义如图2所示。


740)this.width=740" border=undefined>
    每一帧数据中开始位总是为0,数据校验采用奇校验方式,停止位始终为1。从设备到主设备通信时,从设备总是在时钟线为高时改变数据线状态,主设备在时钟下降沿读人数据线状态。
(2)主设备到从设备的通信
    主设备与从设备进行通信时,主设备首先会把时钟线和数据线设置为“请求发送”状态。具体方式为:首先下拉时钟线至少100 us来抑制通信,然后下拉数据线“请求发送”,最后释放时钟线。在此过程中,从设备在不超过 10us的间隔内就要检查这个状态。当设备检测到这个状态时,将开始产生时钟信号。
    此时数据传输的每一帧由12位构成,其时序和每一位含义如图3所示。


740)this.width=740" border=undefined>
    与从设备到主设备通信相比,其每帧数据多了一个ACK位。这是从设备应答接收到的字节的应答位,由从
设备通过拉低数据线产生,应答位ACK总是为。。主设备到从设备通信过程中,主设备总是在时钟为低电平时改变数据线的状态,从设备在时钟的上升沿读入数据线状态。
2  PS/2键盘的编码与命令集
(1) PS/2扭盘的编码
    现在PC机使用的PS/2键盘都默认采用第二套扫描码集。该扫描码集可参考文献[1]。扫描码有两种不同的
类型:通码(make code)和断码(break code)。当一个键被按下或持续按住时,键盘会将该键的通码发送给主机;而当一个键被释放时,键盘会将该键的断码发送给主机。
    根据键盘按键扫描码的不同,在此可将按键分为如下几类:
    第一类按键,通码为1字节,断码为OxFO+通码形式。如A键,其通码为Ox1C,断码为OxFO Ox1C, 第二类按键,通码为2字节0 xEO + 0 xXX形式,断码为OxEO+OxFO+OxXX形式。如 right ctrl键,其通码为OxEO 0x14,断码为OxEO OxFO 0x14,    第三类特殊按键有两个,print screen键通码为OxEO 0x12 OxEO Ox7C,断码为 OxEO OxFO Ox7C OxEO OxFO 0x12; pause键通码为Ox El 0x14 0x77 OxEl OxFO 0x14 OxFO 0x77,断码为空。
    组合按键的扫描码发送按照按键发生的次序,如以下面顺序按左SHIFT+A键:1按下左SHIFT键,2按下 A
键,3释放A键,4释放左SHIFT键,那么计算机上接收到的一串数据为0x12 Ox1C OxFO Ox1C OxFO 0x12, 在驱动程序设计中,就是根据这样的分类来对不同的按键进行不同处理的。
(2) PS/2键盘的命令集
    主机可以通过向PS/2键盘发送命令来对键盘进行设置或者获得键盘的状态等操作。每发送一个字节,主机都会从键盘获得一个应答0 xFA“重发resend"和“回应echo',命令例外)。下面简要介绍驱动程序在键盘初始化过程中所用的指令(详细键盘命令集见参考文献[1]):    OxED主机在本命令后跟随发送一个参数字节,用于指示键盘上num lock, caps lock, scroll lock led的状态;    OxF3主机在这条命令后跟随发送一个字节参数来定义键盘机打的速率和延时; OxF4用于在当主机发送OxF5禁止键盘后,重新使能键盘。
3  PS/2键盘与单片机的连接电路
    PS/2键盘与AT89C51单片机的连接方式如图4所示。Pi. 0接 PS/2数据线,P3. 2 (INTO)接 PS/2时钟线。
因为单片机的P1,P3口内部是带上拉电阻的,所以PS/2的时钟线和数据线可以直接与单片机的P1,P3相连接。


740)this.width=740" border=undefined>
4 驱动程序设计
    驱动程序使用Keil C51语言,Keil uVision2编程环境。PS/2 104键盘驱动程序的主要任务,是实现单片机与键盘间PS/2通信,以及将接收到的按键扫描码转换为该按键的键值KeyVal,提供给系统上层软件使用。
(1)单片机与健盘间PS/2通信的程序设计
    在PS/2通信过程中,主设备(单片机)是在时钟信号为低时发送和接收数据信号的。因为单片机到键盘发送的是指令,需要键盘回应,所以这部分程序采用查询方式;而单片机接收键盘数据时,数据线上的信号在时钟为低时已经稳定,所以这部分程序采用中断方式,且不需要在程序中加人延时程序。
(2)健盘扫描码转换程序设计
    由于键盘扫描码无规律可循,因此由键盘扫描码获得相应按键的键值(字符键为其ASCII值,控制键如Fl,
CtrL等为自定义值),只能通过查表的方式。由于按键的三种类型及部分按键对应着两个键值(如A键的键值
根据CAPS和 SHIFT键状态有 0x41 (A)和 Ox61(a)两种),因此综合考虑查表转换速度和资源消耗,设计中使用4个键盘表:键盘扫描码转换基本集和切换集kb-plain_map[ NR_ KEYS]与kb- shift- map[ NR_ KEYS];包含EO前缀的键盘扫描码转换基本集和切换集kbe0_plain_map[N又KEYS〕与kbe0_ shift-map [ NR_ KEYS]。PS/2 104键盘按键扫描码最大值为0x83,所以设置NR_ KEYS为132。所有四个键盘表的定义均为如下形式:KB_ MAP
[ MAKE CODE] = KEYVAL,如果扫描码对应的按键为空,如KB_MAP[0x00],则定义相应键值为NULL-KEY(0x00)。以下是键盘扫描码基本集的部分代码实例:
kb_plain_map[NIZKEYS] ={……
NULL- KEY; Ox2C; Ox6B; 0x69;Ox6F;Ox3O;0x39;NULL_
KEY;//扫描码Ox4O-Ox47
刀对应按键 空,逗号,K,I,0,0,9,空
//对应键值0x00,’,’,'k','i','o','0','9',0x00
……};
    如此设计键盘转换表的另一个好处在于,以后如需扩展支持有ACPI, Windows多媒体按键键盘时,只需要将键表中相应处修改即可。如ACPI power按键通码为OxEO 0x37,修改 kbeO _ plain- map [ 0x37 ] = KB _ACPI_PWR即可。
    特殊按键PAUSE使用单独程序处理,如果接收到OxEl就转入这段程序;而print screen键则将其看作是两
个通码分别为OxEO 0x12和OxEO Ox7C的“虚键,,的组合键来处理。
    在驱动程序中声明如下全局变量:led-status其bit0一scroll lock led关0、开 1; bitl一num lock led关为。,开为1; bit2一caps lock led关为0,开为1; bit3-bit?总是。;agcs_status记录左右shift ctrl gui alt状态,bit0一左shift键,bitl一左。trl键,bit2一左gui键, bit3一左alt键,bit4-右shift键,bit5一右ctrl键,bit6一右gui键,bit7一右alt键,相应键按下则对应位为I,释放为。。EO_FLAG接到
OxEO置1; El FLAG接收到OxEl置1; FO-FLAG接收到OxFO置1。按键键值通过Keyval提供给上层使用。
    PS/2键盘扫描码键值转换程序ps2_codetrans()流程如图5所示。
    第一类按键的扫描码键值转换程序代码:
if (FO-FLAG) t//接收扫描码为断码
  switch (mcu_revchar){//处理控制键
    case 0x11:agcs_status& = OxF7;break;//左alt释放
    case 0x12:agcs_status & =0xFE; break; //左shift释放
    case 0x14:agcs_status&=OxFD; break;//左ctrl释放
    case 0x58:if (1e走status&0x04)
            le走status&二0x03; //caps lock键
              else led_statusl =0x04;
              ps2_ledchange();
                break;
    case 0x59; agcs_status&二OxEF;break;//右shift释放
    case 0x77:if (led status&0x02 )
            led_status& = 0x05; //num lock键
              else led_status{ =0x02;
              ps2_ledchange();
                break;
    case Ox7E; if(led_status&0x01)
              led_status&=0x06; //scroll lock键
              else led_statusI =0x01;
              ps2_ledchange();
                break;
    default; break;
  }
  FO-FLAG = 0;lse { //接收扫描码为通码
  if (1e走status衣0x04) caps flag=1;else caps-flag二0;
  if (led-status & 0x02) num_flag=1;else num-flag二0;
  if (scga_status&0x11) shift flag=1;else shift flag=0;
  刀扫描码键值转换
  if ((caps flag==shift-flag)}1(!num_flag)) KeyVal=b_plain_map[mciLrevchar];
  else KeyVal二 kb-shift  map[mcu_revcha];
  switch (mcu-revchar){ //处理控制键或状态键
    case 0x11: agcs_statusl二0x08;//左alt按下
    case 0x12: ages-status}二0x01;//左shift按下
    case 0x14: ages-status}二0x02;//左ctrl按下
    case 0x59:agcs_status}二0x10;//右shift按下
    default: break;
  }
}


740)this.width=740" border=undefined>
    第二类按键的扫描码键值转换程序与上相似。要注意的是在退出该程序段时对EO- FLAG和FO_FLAG标志的清0。
    PAUSE键的处理程序:如果接收到OxEl,置El-FLAG= 1,然后顺次将后续接收到的7个字节数据和PAUSE的通码后7个字节比较,一致则返回KeyVal =KB PAUSE。在比较完所有 7个字节后清除El_ FLAG标志。
    键盘初始化程序kb_init()流程:
    ① 上电后,接收键盘上电自检通过信号0 xAA,或者自检出错信号OxFC。单片机接收为OxAA,进人下一步,否则,进行出错处理。
    ② 关 LED指示,单片机发送 OxED,然后接收键盘回应0 xFA,接着发送0x00接收O xFA,
    ③ 设置机打延时和速率。单片机发送 0xF3,接收0 xFA,发送OxOO(250ms,2. Ocps),接收OxFA,
    ④ 检查LED,发送 0 xED,接收0 xFA,发送0x07开所有 LED),接收 OxFA。发送 0 xED,接收 0 xFA,发送0x00(关 LED),接收OxFA,
    ⑤允许键盘发送OxF4,接收0 xFA,键盘LED改变ps2_ledchange()函数流程:发送0 xED "接收0 xFA"发送led-status"接收。xFA.
结 语
    该驱动程序经Keil uVision2编译,在AT89C51单片机上运行通过,实现了对 PS/2 104键盘的支持,以及对字符按键大小写切换,num lock切换,控制键及组合按键的支持。该程序对其他嵌入式或单片机系统中PS/2键盘的应用也有借鉴意义。
参考文献
1  Adam Chapweske. The AT一PS/2 Keyboard Interface. http://panda. cs. ndsu. nodak. edu/oo 7Eachapwes/PICmicro/ keyboard/ atkeyboard.html
2   Adam Chapweske. PS/2 Mouse/Keyboard Protocol. http://govschl. ndsu. nodak edu/-achapwes/PICmicro/PS2/ps2. htm
3  Network Technologies Incorporated PS/2 Keyboard&Mouse Protocols. http://www.networktechinc. com/ps2一prots. html
4   Linux 2. 4. 10内核程序defkeymap. c do-keyb. c kbd. c keyb-dev. c keyboard. c kbd_kern. h kd. h keyboard. h


         
          [/td]
        [/tr]
      
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|文字版|手机版|DIY编程器网 ( 桂ICP备14005565号-1 )

GMT+8, 2024-9-26 04:25 , 耗时 0.095805 秒, 18 个查询请求 , Gzip 开启.

各位嘉宾言论仅代表个人观点,非属DIY编程器网立场。

桂公网安备 45031202000115号

DIY编程器群(超员):41210778 DIY编程器

DIY编程器群1(满员):3044634 DIY编程器1

diy编程器群2:551025008 diy编程器群2

QQ:28000622;Email:libyoufer@sina.com

本站由桂林市临桂区技兴电子商务经营部独家赞助。旨在技术交流,请自觉遵守国家法律法规,一旦发现将做封号删号处理。

快速回复 返回顶部 返回列表