网站导航: 首页 > 设计参考 > 正文 文章搜索
单片机系统中PS/2键盘驱动程序的设计[图]
 
文章编号:
090106133143
文章分类: 单片机 51系列
点 击:
...
关 键 词: PS/2键盘
文章来源:
网络
摘 要:
文中在介绍PS/2协议和PS/2键盘工作原理与特点的基础上,给出了一个在单片机上实现对PS/2键盘支持的硬件连接与驱动程序设计实现...

 单片机由PS/2键盘接收数据程序:外部中断0设置为下降沿触发
 

 
  1. void int0() interrupt 0 using 0 {//   
  2.     EX0=0; //关外部中断0   
  3.     switch(ps2_revchar_cnt){   
  4.     case 1:   
  5.         ……   
  6.     case 8:mcu_revchar<<=1;   
  7.         if(PS2_SGN_DATA) mcu_revchar |= 0x01;   
  8.         ps2_revchar_cnt++;   
  9.         break;   
  10.     case 0:ps2_revchar_cnt++;break//开始位,   
  11.     case 9:ps2_revchar_cnt++;break//校验位,可添加校验程序   
  12.     case 10: _nop_();//停止位   
  13.         ps2_revchar_cnt= 0;   
  14.         revchar_flag=1;//置接收到数据标识位   
  15.         break;   
  16.     default:break;   
  17.     }   
  18.     EX0=1;//开外部中断0   
  19. }   

4.2 键盘扫描码转换程序设计
    由于键盘扫描码无规律可循,因此由键盘扫描码获得相应按键的键值(字符键为其ASCII值,控制键如F1,Ctrl等为自定义值),只能通过查表的方式获得.由于按键的3种类型及部分按键对应着两个键值(如A键的键值根据Caps和Shift键状态有0x41(A)和0x61(a)两种),因此综合考虑查表转换速度和资源消耗,设计中使用4个键盘表:键盘扫描码转换基本集和切换集(kb_plain_map[NR_KEYS]与kb_shift_map[NR_KEYS]);包含E0前缀的键盘扫描码转换基本集和切换集(kbeO_plain_map[NR_KEYS]与kbe0_shiftmap[NR_KEYS]).PS/2 104键盘按键扫描码最大值为0x83,所以设置NR_KEYS为132.所有4个键盘表的定义均为如下形式:KB_MAP[MAKE CODE]=KEYVAL,如果扫描码对应的按键为空(如KB_MAP[0x00]),则定义相应键值为NULL_KEY(0x00).以下是键盘扫描码基本集的部分代码实例:

 
  1. kb_plain_map[NR_KEYS]=   
  2. {……   
  3.     NULL_KEY;0x2C;0x6B;0x69;0x6F;0x30;0x39;   
  4.     NULL_KEY; //扫描码0x40~0x47   
  5. //对应按键空,逗号,K,I,O,0,9,空   
  6. //对应键值0x00,',','k','i','o','O','9',0x00……    
  7. };   

    如此设计键盘转换表的另一个好处在于,以后如需扩展支持有ACPI、Windows多媒体按键键盘时,只需要将键表中相应处修改即可,如ACPI
Power按键通码为0xE0 0x37,修改kbe0_plain_map[0x37]=KB_ACPI_PWR即可.
    特殊按键Pause使用单独程序处理,如果接收到0xE1就转入这段程序.而Print Screen键则将其看作是两个通码分别为0xE0 0x12和0xE0 0x7C
的“虚键”的组合键处理.在驱动程序中设定如下全局变量:led_status记录Scroll Lock Led,Num Lock Led和Caps Lock Led的状态(关为0,开为1);agcs_status记录左右Shift Ctrl Gui Alt状态,相应键按下则对应位为1,释放为0.E0_FLAG接到0xE0置1;E1_FLAG接收到0xE1置1;F0_FLAG接收到0xF0置1.按键键值通过KeyVal提供上层程序使用.PS/2键盘扫描码键值转换程序ps2_codetrans()流程框架如图5所示.
扫描码键值转换程序流程框架 

第1类按键的扫描码键值转换程序代码。

 

 
  1. if(F0_FLAG){//接收扫描码为断码   
  2.     switch(mcu_revchar){//处理控制键   
  3.     case 0x11:ages_status&=0xF7;break;//左alt释放   
  4.     case 0x12:ages_status&=0xFE;break;//左shift释放   
  5.     case 0x14:agcs_status&=0xFD;break;//左ctrl释放   
  6.     case 0x58:   
  7.         if(led_status&0x04)    
  8.             led_status &= 0x03; //caps lock   
  9.         else    
  10.             led_status |=0x04;   
  11.         ps2_ledchange();   
  12.         break;   
  13.     case 0x59: agcs_status &= 0xEF;break;//右shift释放   
  14.     case 0x77:    
  15.         if(led_status&0x02)   
  16.             led_status&=0x05;//num lock   
  17.         else    
  18.             led_status |=0x02;   
  19.         ps2_ledchange();   
  20.         break;   
  21.     case 0x7E:   
  22.         if(led_status&0x01)    
  23.             led_status&=0x06;//scroll lock   
  24.         else    
  25.             led_status |=0x01;   
  26.         ps2_ledchange();   
  27.         break;   
  28.     default;break;   
  29.     }   
  30.     F0_FLAG=0;   
  31. }   
  32. else{//接收扫描码为通码   
  33.     if(led_status&0x04) caps_flag=1;else caps_flag = 0;   
  34.     if(led_status&0x02) num_flag =1;else num_flag =0;   
  35.     if(agcs_status&0x11) shift_flag = 1;else  
  36.         shift_flag=0;   
  37.     //扫描码键值转换   
  38.     if((caps_flag == shift_flag) || (!num_flag))   
  39.         KeyVal=kb_plain_map[mcu_revchar];   
  40.     else    
  41.         KeyVal = kb_shift_map[mcu_revchar];   
  42.     switch(mcu_revchar){//处理控制键或状态键   
  43.     case 0x11:agcs_status|= 0x08;//左alt按下   
  44.         Case 0x12:agcs_status|= 0x01;//左shift按下   
  45.     case 0x14:agcs_status|= 0x02;//左ctrl按下   
  46.     case 0x59:agcs_status|= 0x10;//右shift按下   
  47.     default:break;   
  48.     }   
  49. }   

    第2类按键的扫描码键值转换程序与上面相似.注意:在退出该程序段时,对E0_FLAG和F0_FLAG标识清0.Pause键的处理程序,如果接收到0xE1,置E1_FLAG=1,然后顺次将后续接收到的7个字节数据和Pause的通码后7个字节比较,一致则返回KeyVal=KB_PAUSE;在比较完所有7个字节后清除E1_FLAG标识.键盘初始化程序kb_init()流程为:
① 上电后,接收键盘上电自检通过信号0xAA,或者自检出错信号0xFC.单片机接收为0xAA则进入下一步,否则进行出错处理.
② 关LED指示,单片机发送0xED,然后接收键盘回应0xFA,接着发送0x00接收0xFA.
③ 设置机打延时和速率:单片机发送0xF3,接收0xFA,发送0x00(250 ms,2.0 cps),接收0xFA.
④ 检查LED,发送0xED,接收0xFA,发送0x07(开所有LED),接收0xFA.发送0xED,接收0xFA,发送0x00(关LED),接收0xFA.
⑤ 允许键盘,发送0xF4,接收0xFA.键盘LED改变ps2_ledchange()函数流程:发送0xED;接收0xFA;发送led_status;接收0xFA.

5 结语
  该驱动程序经Keil uVision2 编译,在AT89C51单片机上运行通过,实现了对PS/2 104键盘的支持,实现了对字符按键大小写切换,Num Lock切换、控制键及组合按键的支持.同时该程序对其他嵌入式或单片机系统中PS/2键盘的应用也有借鉴意义.

 
相关文章:

上一页 12
 
最新开源项目
 
 
  查看更多...  
 
本站相关产品   淘宝网店
 




 
  查看更多...  

 

本站程序由百合电子工作室开发和维护
Copyright @ baihe electric studio
渝ICP备09006681号-4