[置顶] C51模拟PS2键盘(一)

*************************************************************************************

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。

否则将追究法律责任。http://blog.csdn.net/fulinus/article/details/15112877

*************************************************************************************

协议介绍:

  一. PS2接口
   1> 现在的Ps2接口普遍采用6引脚连接器.主设备采用female接口,从设备采用male接口
  
   2> 6引脚连接器引脚设置:
   1> 引脚1 -> 数据线
   2> 引脚2 -> 未定义,保留
   3> 引脚3 -> 电源地
   4> 引脚4 -> 电源<+5V>
   5> 引脚5 -> 时钟线
   6> 引脚6 -> 未定义,保留
  
   3> Ps2的两根信号线为"集电极开路"结构,必须要有上拉电阻.并且一般情况下,在主设备端上拉.
  
  二. PS2协议
   1> Ps2协议为"双向同步串行"协议.主设备拥有总线上的优先权,它可以通过拉低总线上时钟线来抑制从设备发送.
  
   2> 从设备发送到主设备的数据,在时钟信号的下降沿(CLK由高到低)被主设备读取.从设备在时钟信号高电平状态改变数据位.
  
   从设备发送到主设备,一帧数据为11个Bits.包括:
   1> 起始位<1 bit>,总为0
   2> 数据位<8 bit>,低位在前
   3> 校验位<1 bit>,奇校验
   4> 停止位<1 bit>,总为1
  
   从设备进行发送过程,必须查询总线上时钟线状态,确认为高电平才能发送<时钟信号低电平为主机抑制通讯>,否则缓冲发送数据直到获得总线控制权.
  
   模拟从设备发送, 从时钟脉冲的上升沿到一个数据转变的时间至少要有5us.
   从数据变化到时钟脉冲的下降沿的时间至少要有5us并且不大于25us.
  
   主设备可以在第11个时钟脉冲<停止位>之前把线拉低,导致从设备放弃发送当前字节<这是非常罕见的>.
  
   从设备发送完停止位之后,在发送下一个数据包之前,必须等待至少50us.主设备在这段时间内处理接收到的数据并且抑制数据发送.
  
   主设备在接收到一个数据包之后,通常都抑制数据发送以保证对接收到的数据进行处理.
  
   从设备应该在主设备停止发送抑制之后等待至少50us后,才能发送数据.
  
   模拟从设备发送一帧数据到主设备过程:
   1> 等待时钟线为高. 
   2> 延时50us 
   3> 时钟线依然为高? 
   Yes -> 步骤4 
   No -> 步骤1 
   4> 数据线是否为高? 
   Yes -> 步骤5 
   No -> 准备接收主机发送数据 
   5> 等待20us 
   6> 调用BitSend发送起始位(0). 
   7> 判断时钟线是否被拉低<主机抑制发送> 
   Yes -> 发送发送,退出发送过程 
   No -> 继续 
   8> 调用BitSend发送8位数据 
   低位先发送 
   每发送一位,测试时钟线是否被拉低 
   Yes -> 发送发送,退出发送过程 
   No -> 继续 
   9> 调用BitSend发送奇校验位 
   10> 判断时钟线是否被拉低<主机抑制发送> 
   Yes -> 发送发送,退出发送过程 
   No -> 继续 
   11> 调用BitSend发送停止位(1) 
   12> 延时30us 
   
   BitSend 函数 
   1> 设置数据线 
   2> 延时20us 
   3> 拉低时钟线 
   4> 延时40us 
   5> 释放时钟线 
   6> 延时20us 
   
   3> 主设备发送到从设备的数据,在时钟信号的上升沿(CLK由低到高)被从设备读取.主设备在时钟信号低电平状态改变数据位.
   
   主设备发送到从设备,一帧数据为12个Bits.包括
   1> 起始位<1 bit>,总为0
   2> 数据位<8 bit>,低位在前
   3> 校验位<1 bit>,奇校验
   4> 停止位<1 bit>,总为1
   5> 应答为<1 bit>,总为0
  
   主设备要发送,必须先把时钟线,数据线设置为"请求发送"状态
   1> 下拉时钟线至少100us抑制通讯
   2> 下拉数据线应用发送请求,释放数据线.
  
   主设备可以在第11个时钟脉冲(应答位)前中止发送,只需要下拉时钟线至少100us抑制通讯
  
   主设备发送过程应答位的改变在时钟线为高时候,不同于其他11位在时钟线为低时候改变.
  
   模拟主设备发送一帧数据到从设备过程
   
   1> 拉低时钟线 
   2> 延时100us 
   3> 拉低数据线 
   4> 释放时钟线 
   5> 等待时钟线被拉低 
   6> 发送8位数据位 
   低位在前 
   等待时钟线拉高 
   等待时钟线拉低 
   7> 发送及校验位 
   8> 等待时钟线拉高 
   9> 等待时钟线拉低 
   10> 释放数据线(StopBit总为1) 
   11> 等待数据线被拉低(AckBit总为0) 
   12> 等待时钟线被拉低 
   13> 等待数据线/时钟线释放 
   
   Ps2总从发送时序比较图中[a]必须不大于15ms [b]必须不大于2ms,否则主设备产生一个错误
  
   如果主设备发送的命令要求有一个回应,这个回应必须在主设备释放时钟线后20ms之内被收到.如果没有收到则主机产生一个错误.
   
   模拟从设备接收主设备发送的一帧数据过程:
   
   接收程序必须每10ms检测一次数据线是否为低,如果数据线被主设备拉低,则从主设备读取一个字节.
   
   1> 等待时钟线为高 
   2> 判断数据线是否为低 
   Yes 
   No -> 错误,放弃接收 
   3> 读取8位数据 
   每读取一位后判断时钟线是否被拉低 
   4> 读取奇校验位 
   5> 判断时钟线是否被拉低 
   6> 读取停止位 
   7> 判断时钟线是否被拉低 
   8> 判断数据线是否为0 
   Yes -> 保持时钟线直到数据线为1后,产生一个错误
   No 
   9> 发送应答位 
   10> 判断奇校验结果 
   Right -> 
   Wrong -> 产生一个错误 
   11> 延时45us<给主机时间抑制传输> 
   
   BitGet 函数 
   1> 延时20us 
   2> 拉低时钟线 
   3> 延时40us 
   4> 释放时钟线 
   5> 延时20us 
   6> 读取数据线 
   
   SendAckBit 函数 
   1> 延时15us 
   2> 拉低数据线 
   3> 延时5us 
   4> 拉低时钟线 
   5> 延时40us 
   6> 释放时钟线 
   7> 延时5us 
   8> 释放数据线 
   
   注: 所有时序的时限限制为总的延时时间,包括指令执行时间在内.所以程序书写时候,依据不同芯片指令执行时间的长短需作适当调整.


这是C51模拟PS2键盘的主程序:

/*********************************************************************************
 *      Copyright:  (C) 2012 fulinux<[email protected]> 
 *                  All rights reserved.
 *
 *       Filename:  main.c
 *    Description:  This is the main file of this program
 *                 
 *        Version:  1.0.0(10/27/2011~)
 *         Author:  2012 fulinux<[email protected]>
 *      ChangeLog:  1, Release initial version on "10/27/2012 11:39:10 AM"
 *                 
 ********************************************************************************/

#include <C8051F310.h>                 // SFR declarations

#include "Initialize.h"

#include "delay.h"

#include "PS_2.h"

#include "key.h"   

//#define	 Init_NUM	3																    


//-----------------------------------------------------------------------------
// main() Routine
//-----------------------------------------------------------------------------

void main (void)
{										 				  
	PCA0MD &= ~0x40;
	
	Oscillator_Init();

	Port_Init();							  	
              
	while(1)
	{	
		PS2_Response();
		key_scan();		 				
	}
}

*************************************************************************************

C51模拟PS2键盘(二):原文链接

*************************************************************************************


你可能感兴趣的:(fulinux,模拟PS2键盘,PS2键盘,C51模拟PS2键盘)