基于pic32的ps/2键盘通讯协议(mcu to keyboard)-凯发app官方网站

凯发app官方网站-凯发k8官网下载客户端中心 | | 凯发app官方网站-凯发k8官网下载客户端中心
  • 博客访问: 127061
  • 博文数量: 22
  • 博客积分: 596
  • 博客等级: 二等列兵
  • 技术积分: 874
  • 用 户 组: 普通用户
  • 注册时间: 2011-04-06 12:09
个人简介

enjoy code,enjoy life!

文章分类
文章存档

2013年(11)

2012年(11)

相关博文
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·

分类: 嵌入式

2012-07-25 08:47:16

                         mcu到keyboard的通讯协议
 
注:mcu到keyboard的通讯主要用在控制键盘上的led灯(numlock,capslock和scrolllock)
 
1.首先介绍下ps/2接口和发送的帧位:
   如图1和图2所示,ps/2的接口定义如下:
     
                         图1.ps/2接口定义
 
 
               
                          图2.ps/2接口母座定义
 
   图3为ps/2串行通讯协议中每帧11位数据的定义,如下图所示:
   
                      图3.ps/2每帧11位的串行协议
 
2.ps/2协议的详细通讯过程
    ps/2设备总是产生时钟信号.如果主机要发送数据,它必须首先把时钟和数据线设置为"请求发送"状态.可以通过下拉时钟线至少100微秒来抑制通讯,通过下拉数据线来应用"请求发送",然后释放时钟.设备应该在不超过10毫秒的间隔内就要检查这个状态.当设备检测到这个状态,它将开始产生时钟信号,并且时钟脉冲标记下输入八个数据位和一个停止位.主机仅当时钟线为低的时候改变数据线,而数据在时钟脉冲的上升沿被锁存.这在发生在设备到主机的通讯的过程中正好相反.在停止位发送后不释放数据线,设备将继续产生时钟脉冲直到数据线被释放(然后设备将产生一个错误).
    要使得这个过程易于理解,主机必须按下面的步骤发送数据到ps/2设备:
1.把时钟线拉低至少100微秒.
2.把数据线拉低.
3.释放数据线.
4.等待设备把时钟线拉低.
5.设置/复位数据线发送第一个数据位.
6.等待设备把时钟线拉高.
7.等待设备把时钟线拉低.
8.重复5~7步骤,发送剩下的7个数据位和校验位.
9.释放数据线.
10.等待设备把数据线拉低.
11.等待设备把时钟线拉低.
12.等待设备释放数据线和时钟线.
 
                                图4.主机到设备的详细通讯过程
 
 
3.如下是debug版的host to device的ps/2通讯代码:
    其中有很多处return,主要是用于观测返回值,看看通讯出错的地方.另外timer_10ms[4]是一个定时器,防止程序死机用的.如果调试成功也可以把这些都去掉.

点击(此处)折叠或打开

  1. #define  ps2kb_sendbyte_success    0
  2. byte _ps2kb_sendbyte(byte idata)
  3. {
  4.      byte i;
  5.      byte temp;
  6.      byte tempc;
  7.      bool flag_check = 1;

  8.        temp = idata;
  9.        for(i = 0; i < 8; i)
  10.      {
  11.             tempc = temp & 0x01;
  12.             if(tempc == 0x01)
  13.                 flag_check = !flag_check;
  14.             temp = temp >> 1;
  15.      }
  16.        pd_ps2_clk_tris = 0;

  17.        pd_ps2_clk_lat = 0;

  18.        delay_us(100); //bring the clock line low for at least 100 microseconds
  19.        pd_ps2_data_tris = 0;
  20.            
  21.        pd_ps2_data_lat = 0;//bring the data line low
  22.       
  23.        delay_us(20);
  24.        pd_ps2_clk_tris = 1; //release the clock line.

  25.        
  26.        temp = idata;
  27.        for(i = 0; i < 8; i)
  28.      {        
  29.             tempc = temp & 0x01;

  30.             while( timer_10ms[4]&& pd_ps2_clk_io ); //wait for the device to bring the clock line low
  31.             if( ! timer_10ms[4] ) return (ii1);    
  32.                          
  33.             if(tempc == 0x01) //set/reset the data line to send the data bit
  34.                 pd_ps2_data_lat = 1;
  35.             else
  36.                 pd_ps2_data_lat = 0;
  37.             temp = temp >> 1;
  38.             while( timer_10ms[4]&& !pd_ps2_clk_io ); //wait for the device to bring clock high.
  39.             if( ! timer_10ms[4] ) return (ii2);

  40.                
  41.      }
  42.        while( timer_10ms[4]&& pd_ps2_clk_io ); //wait for the device to bring the clock line low
  43.        if( ! timer_10ms[4] ) return 17;

  44.        if(flag_check == 0x01) //set/reset the data line to send the parity bit
  45.              pd_ps2_data_lat = 1;
  46.      else
  47.             pd_ps2_data_lat = 0;
  48.        
  49.        while( timer_10ms[4]&& !pd_ps2_clk_io ); //wait for the device to bring the clock line high.
  50.        if( ! timer_10ms[4] ) return 18;

  51.        while( timer_10ms[4]&& pd_ps2_clk_io ); //wait for the device to bring the clock line low
  52.        if( ! timer_10ms[4] ) return 19;
  53.        
  54.        pd_ps2_data_tris = 1; //release the data line

  55.        while( timer_10ms[4]&& pd_ps2_data_io ); //wait for the device to bring data low
  56.        if( ! timer_10ms[4] ) return 20;

  57.        while( timer_10ms[4]&& pd_ps2_clk_io ); //wait for the device to bring clock low
  58.        if( ! timer_10ms[4] ) return 21;
  59.       

  60.        while( timer_10ms[4]&& (!pd_ps2_data_io || !pd_ps2_clk_io) ); //wait for the device to release data and clock
  61.        if( ! timer_10ms[4] ) return 22;
  62.        

  63.        // the following is to receive the ack data
  64.        
  65.        while( timer_10ms[4]&& pd_ps2_clk_io ); //wait for the device to bring the clock line low
  66.        if( ! timer_10ms[4] ) return (23);
  67.        
  68.        if(pd_ps2_data_io) return (24);//read the data line to check the start bit
  69.            
  70.        while( timer_10ms[4]&& !pd_ps2_clk_io ); //wait for the device to bring clock high.
  71.        if( ! timer_10ms[4] ) return (25);
  72.     
  73.        flag_check = 1;

  74.        for(i = 0; i < 8; i)
  75.      {        

  76.             while( timer_10ms[4]&& pd_ps2_clk_io ); //wait for the device to bring the clock line low
  77.             if( ! timer_10ms[4] ) return (ii26);
  78.      
  79.             if(pd_ps2_data_io) flag_check = !flag_check;
  80.                          
  81.             temp |= ((((byte)pd_ps2_data_io) & 0x01) << i);
  82.                        
  83.             while( timer_10ms[4]&& !pd_ps2_clk_io ); //wait for the device to bring clock high.
  84.             if( ! timer_10ms[4] ) return (ii27);
  85.               
  86.      }
  87.       
  88.        if( temp != ps2_keycmd_ack )
  89.        {
  90.              return 42;
  91.        }
  92.        
  93.        while( timer_10ms[4]&& pd_ps2_clk_io ); //wait for the device to bring the clock line low
  94.        if( ! timer_10ms[4] ) return 43;

  95.        if( flag_check) return 44; //read the data line to check the parity bit
  96.                   
  97.        while( timer_10ms[4]&& !pd_ps2_clk_io ); //wait for the device to bring clock high.
  98.        if( ! timer_10ms[4] ) return 45;

  99.       
  100.        while( timer_10ms[4]&& pd_ps2_clk_io ); //wait for the device to bring the clock line low
  101.        if( ! timer_10ms[4] ) return 46;

  102.        if(!pd_ps2_data_io) return 47; //read the data line to check the stop bit
  103.                   
  104.        while( timer_10ms[4]&& !pd_ps2_clk_io ); //wait for the device to bring clock high.
  105.        if( ! timer_10ms[4] ) return 48;
  106.        return ps2kb_sendbyte_success;
  107. }
 
 
                          键盘led灯无法点亮问题
   
    尽管有了上面的程序但是我之前也未能实现键盘上led灯的点亮(有些键盘可以,但有些键盘不行),这个问题困扰了我很久,偶然的机会配到一个资深的工程师帮我解决了这个问题,问题如下:
     图1为dr100上ps/2接口部分的电路.因为dr100用的是ttl的电平,所以dr100管脚输出的高电平为3.3v.即ps/2 data端和ps/2 clk端的电平都为3.3v.而ps/2 vcc(即c点电位)为5v.通过计算可得a点与b点的电位约为3.41v.但是由于小键盘采用的是cmos电平,而cmos的高电平是定义为大于3.5v的电平,所以无法驱动小键盘.

  

             图5.ps/2接口电路

待我把r216和r219的电阻短路后后便可以点亮led灯了.


阅读(4420) | 评论(0) | 转发(1) |
0

上一篇:

下一篇:crc校验c语言实现

给主人留下些什么吧!~~
")); function link(t){ var href= $(t).attr('href'); href ="?url=" encodeuricomponent(location.href); $(t).attr('href',href); //setcookie("returnouturl", location.href, 60, "/"); }
网站地图