PS2接口和协议

        这段时间在处理一个PS2键盘的问题:用自己设计的矩阵键盘模拟PS2键盘,用单片机的I/O口模拟PS2的接口,和主机通讯。

基本介绍:

           虽然现在PS2在实际应用中越来越少,但是PS2在USB出来之前发挥了很大的作用。比如说我们的PS2键盘和PS2的鼠标,现在虽然USB应用广泛,但是还是有许多电脑,保留了PS2接口。

PS2接口和协议_第1张图片PS2接口和协议_第2张图片PS2接口和协议_第3张图片

 

 

上面三个图分别是PS2的键盘,鼠标以及电脑机箱的PS2接口(图中的红色区域)

 

 PS/2接口设备不支持热插拔,强行带电插拔有可能烧毁主板。   

PS/2可以与USB接口互转,即PS/2接口设备可以转成USB,USB接口设备也可以转成PS/2。

PS2引脚定义如下:

PS2接口和协议_第4张图片

 

    PS/2鼠标和键盘履行一种双向同步串行协议,换句话说,每次数据线上发送一 
位数据并且每在时钟线上发一个脉冲就被读入,键盘/鼠标可以发送数据到主机而主 
机也可以发送数据到设备,但主机总是在总线上有优先权。它可以在任何时候抑制 
来自于键盘/鼠标的通讯,只要把时钟拉低即可。

下图是数据线和时钟线在如下状态的时候的通讯。

PS2接口和协议_第5张图片

 

从键盘/鼠标发送到主机的数据在时 钟信号的下降沿,当时钟从高变到低的时候被读取,从主机发送到键盘/鼠标的数据 
在上升沿,当时钟从低变到高的时候被读取。不管通讯的方向怎样,键盘/鼠标总是 
产生时钟信号。如果主机要发送数据它。必须首先告诉设备开始产生时钟信号。最 
大的时钟频率是33kHz而且大多数设备工作在1020kHz如果你要制作一个PS/2设备我 
推荐你把频率控制在15kHz左右这就意味着时钟应该是高40微秒低40微秒 
    所有数据安排在字节中每个字节为一帧包含了11个位,这些位的含义如下 

    1个起始位总是为0 
    8个数据位低位在前 
    1个校验位奇校验 
    1个停止位总是为1 
    如果数据位中包含偶数个1,校验位就会置1;如果数据位中包含奇数个1,校验 
位就会置0,数据位中1的个数加上校验位总为奇数,这就是奇校验,这是用来错误 
检测。 
    当主机发送数据给键盘/鼠标时,设备回送一个握手信号来应答数据包已经收 
到,这个位不会出现在设备发送数据到主机的过程中,设备到主机的通讯过程数据 
和时钟线都是集电极开路结构,正常保持高电平当键盘或鼠标等待发送数据时它首 
先检查时钟以确认它是否是高电平,如果不是,那么是主机抑制了通讯,设备必须 
缓冲任何要发送的数据直到重新获得总线的控制权。键盘有16字节的缓冲区而鼠标 
的缓冲区仅存储最后一个要发送的数据包,如果时钟线是高电平设备就可以开始传 
送数据。 
    每位在时钟的下降沿被主机读入,时钟频率为10--16.7kHz。从时钟脉冲的上升沿 
到一个数据转变的时间至少要有5微秒,数据变化到时钟脉冲的下降沿的时间至少要 
有5微秒并且不大于25微秒,这个定时非常重要你应该严格遵循它!主机可以在第11 
个时钟脉冲停止位之前把线拉低,导致设备放弃发送当前字节。这是非常罕见的。 
在停止位发送后,设备在发送下个包前至少应该等待50毫秒,这将给主机时间,当 
它处理接收到的字节时抑制发送,主机在收到每个包时通常自动做这个,在主机释 
放抑制后设备至少应该在发送任何数据前等50毫秒 
    我推荐下面的过程发送一个单一字节从仿真键盘/鼠标到主机 

仿真键盘/鼠标到主机
    1)等待Clock =high 
    2)延时50微秒 
    3)Clock s仍旧为high? 
    No—到第1步 
    4)Data=high 
    No—放弃(并且从主机读取字节) 

 5)延迟20毫秒(=40微秒tothe time Clock ispulled low in sending the start bit。) 
    6)输出起始位(0)\在发送所有这些位的每一位后 
    7)输出8个数据位>测试时钟确认主机是否把它拉低了 
    8)输出校验位/这说明主机要放弃这次传送 
    9)输出停止位(1) 
    10)延迟30毫秒 
    按如下的过程发送单个位 
    1)设置/复位数据 
    2)延迟20微秒 
    3)把时钟拉低 
    4)延迟40微秒 
    5)释放时钟 
    6)延迟20微秒 

外设----主机时序图如下所示

PS2接口和协议_第6张图片

PS2接口和协议_第7张图片

 

PS2接口和协议_第8张图片

 

主机到设备的通讯 
    被发送的包有点不同于主机到设备通讯过程,首先PS/2设备总是产生时钟信 
号。如果主机要发送数据它必须首先把时钟和数据线设置为请求发送状态,如下: 
    通过下拉时钟线至少100微秒来抑制通讯通过下拉数据线来应用请求发送然后释 
放时钟设备应该在不超过10毫秒的间隔内就要检查这个状态,当设备检测到这个状 
态它将开始产生时钟信号并且时钟脉冲标记下输入八个数据位和一个停止位,主机 
仅当时钟线为低的时候改变数据线,而数据在时钟脉冲的上升沿被锁存,这在发生 
在设备到主机通讯的过程中正好相反,在停止位发送后设备要应答接收到的字节就 
把数据线拉低并产生最后一个时钟脉冲,如果主机在第11个时钟脉冲后不释放数据 
线,设备将继续产生时钟脉冲直到数据线被释放,然后设备将产生一个错误,主机 
可以在第11个时钟脉冲应答位前中止一次传送,只要下拉时钟线至少100微秒,要使 
得这个过程易于理解主机必须按下面的步骤发送数据到PS/2设备 
    1)把时钟线拉低至少100微秒 
    2)把数据线拉低 
    3)释放数据线 
    4)等待设备把时钟线拉低 
    5)设置/复位数据线发送第一个数据位 
    6)等待设备把时钟拉高 
    7)等待设备把时钟拉低 
    8)重复5-7步 发送剩下的7个数据位和校验位 
    9)释放数据线 
    10)等待设备把数据线拉低 
    11)等待设备把时钟线拉低 
    12)等待设备释放数据线和时钟线 
    设备产生的信号注意应答位时序的改变,数据改变发生在时钟线为高的时候, 
不同于其它11位是当它为低的时候,在主机最初把数据线拉低后,设备开始产生时钟 
脉冲的时间必须步大于15ms,数据包被发送的时间必须不大于2ms,如果这两个条 
件不满足,主机将产生一个错误,在包收到后主机为了处理数据立刻把时钟线拉低 
来抑制通讯,如果主机发送的命令要求有一个回应,这个回应必须在主机释放时钟 
线后20ms之内被收到,如果没有收到,则主机产生一个错误,在设备到主机通讯的情 
况中时钟改变后的5微秒内不应该发生数据改变的情况,如果你要仿真一个鼠标或键 
盘我推荐你按如下的过程从主机读入数据,在你的主程序中至少每10毫秒检测数据 
线是否为低,如果数据线已被主机拉低则从主机读取一个字节 
    1)等待时钟线为高 
    2)数据线仍然为低吗 

不有错误发生放弃 
    3)读入8个数据位\在读入这些位后 
    4)读入校验位>测试时钟线数否被主机拉低 
    5)读入停止位/这就意味着放弃这次传送 
    6)数据线仍旧为0吗 
    是保持时钟直到数据1然后产生一个错误 
    7)输出应答位 
    8)检查校验位 
    如果校验位不正确则产生一个错误 
    9)延迟45微秒给主机时间抑制下次的传送 
    按如下次序读取每位8个数据位检验位和停止位 
    1)延迟20微秒 
    2)把时钟拉低 
    3)延迟40微秒 
    4)释放时钟 
    5)延迟20微秒 
    7)读数据线 
    按如下次序发送应答位 
     1)延迟15微秒 
    2)把数据线拉低 
    3)延迟5微秒 
    4)把时钟线拉低 
    5)延迟40微秒 
    6)释放时钟线 
    7)延迟5微秒 
    8)释放数据线 

主机----设备时序图如下所示

 

PS2接口和协议_第9张图片

PS2接口和协议_第10张图片

PS2接口和协议_第11张图片

PS2接口和协议_第12张图片

 

设备到主机的通信 
标准的PS/2鼠标发送位移和按键信息给主机采用如下的3字节数据包格式: 

    位移计数器是一个9位2的补码整数。它的最高位作为符号位出现在位移数据包 
的第一个字节里。这些计数器在鼠标读取输入发现有位移时被更新。这些值是自从 
最后一次发送位移数据包给主机后位移的累计量(即最后一次包发给主机后位移计 
数器被复位)。位移计数器可表示的值的范围是-255到+255,如果超过了范围,相 
应的溢出位就被设置,并且在复位前,计数器不会增减。正如我前面提及的一旦位 
移数据包成功地发送给主机,位移计数器就会复位,同样鼠标在收到主机不是 
Resend 0xFE命令外的其他命令,计数器也会复位。 
下面是PS2键盘的部分按键表

PS2接口和协议_第13张图片

 

 

按键设计的基本流程图如下:

 

PS2接口和协议_第14张图片

 

部分软件设计如下:

void main (void)
{
            unsigned int key_value = 0;     // 初始化按键
            PCA0MD &= ~0x40;                 //关闭看门狗
            Oscillator_Init();                         //系统时钟设置

            Port_Init();                                  //端口设置
           
            while(1)
            { 
                       PS2_Response();                    //和主机通讯
                       key_value = key_scan();          //扫描键盘输入
                       key_send(key_value);               //如果有按键按键按下,则发送对应的键码到主机
                       key_value = 0;                        //按键为0时为空
            }
}

你可能感兴趣的:(单片机及其外设驱动)