一.电气特性

1

DATA

Key Data

2

n/c

Not connected

3

GND

Gnd

4

VCC

Power , +5 VDC

5

CLK

Clock

6

n/c

Not connected

二.数据格式

1个起始位 总是逻辑0
8个数据位 (LSB)低位在前
1个奇偶校验位 奇校验
1个停止位 总是逻辑1
1个应答位 仅用在主机对设备的通讯中

表中,如果数据位中1的个数为偶数,校验位就为1;如果数据位中1的个数为奇数,校验位就为0;总之,数据位中1的个数加上校验位中1的个数总为奇数,因此总进行奇校验。

ps2设备的clock和data都是集电极开路的,平时都是高电平。当ps2设备等待发送数据时,它首先检查clock是否为高。如果为低,则认为PC抑制了通讯,此时它缓冲数据直到获得总线的控制权。如果clock为高电平,ps2则开始向PC发送数据。
一般都是由ps2设备产生时钟信号。发送按帧格式。数据位在clock为高电平时准备好,在clock下降沿被PC读入。

数据从键盘/鼠标发送到主机或从主机发送到键盘/鼠标,时钟都是PS2设备产生.主机对时钟控制有优先权,即主机想发送控制指令给PS2设备时,可以拉低时钟线至少100μS,然后再下拉数据线,最后释放时钟线为高。PS2设备的时钟线和数据线都是集电极开路的,容易实现拉低电平。

PC在时钟的下降沿读取数据.

PS: ps2协议是现在大多数鼠标,键盘与PC通讯的标准协议,鼠标的通讯更为简单些,只是传送的数据内容不一样而已。

三.数据发送时序

键盘接口时序(a) 键盘发送时序;(b) 键盘接收时序

从PS/2向PC机发送一个字节可按照下面的步骤进行:

(1)检测时钟线电平,如果时钟线为低,则延时50μs;
          (2)检测判断时钟信号是否为高,为高,则向下执行,为低,则转到(1);
          (3)检测数据线是否为高,如果为高则继续执行,如果为低,则放弃发送(此时PC机在向 PS/2设备发送数据,所以PS/2设备要转移到接收程序处接收数据);
          (4)延时20μs(如果此时正在发送起始位,则应延时40μs);
         (5)输出起始位(0)到数据线上。这里要注意的是:在送出每一位后都要检测时钟线,以确保PC机没有抑制PS/2设备,如果有则中止发送;
          (6)输出8个数据位到数据线上;
           (7)输出校验位;
           (8)输出停止位(1);
           (9)延时30μs(如果在发送停止位时释放时钟信号则应延时50μs);

通过以下步骤可发送单个位:
           (1)准备数据位(将需要发送的数据位放到数据线上);
           (2)延时20μs;
           (3)把时钟线拉低;
           (4)延时40μs;
           (5)释放时钟线;
           (6)延时20μs。

PS/2设备从PC机接收一个字节

由于PS/2设备能提供串行同步时钟,因此,如果PC机发送数据,则PC机要先把时钟线和数据线置为请求发送的状态。PC机通过下拉时钟线大于100μs来抑制通讯,并且通过下拉数据线发出请求发送数据的信号,然后释放时钟。当PS/2设备检测到需要接收的数据时,它会产生时钟信号并记录下面8个数据位和一个停止位。主机此时在时钟线变为低时准备数据到数据线,并在时钟上升沿锁存数据。而PS/2设备则要配合PC机才能读到准确的数据。具体连接步骤如下:

(1)等待时钟线为高电平。
          (2)判断数据线是否为低,为高则错误退出,否则继续执行。
          (3)读地址线上的数据内容,共8个bit,每读完一个位,都应检测时钟线是否被PC机拉低,如果被拉低则要中止接收。
          (4)读地址线上的校验位内容,1个bit。
          (5)读停止位。
          (6)如果数据线上为0(即还是低电平),PS/2设备继续产生时钟,直到接收到1且产生出错信号为止(因为停止位是1,如果PS/2设备没有读到停止位,则表明此次传输出错)。          
          (7 输出应答位。
          (8) 检测奇偶校验位,如果校验失败,则产生错误信号以表明此次传输出现错误。
          (9)延时45 μs,以便PC机进行下一次传输。

读数据线的步骤如下:

(1)延时20μs;
          (2)把时钟线拉低
          (3)延时40μs
          (4)释放时钟线
          (5)延时20μs
          (6)读数据线。

下面的步骤可用于发出应答位;

(1)延时15μs; (2)把数据线拉低;(3)延时5μs;(4)把时钟线拉低;(5)延时40μs;(6)释放时钟线;(7)延时5μs; (8)释放数据线。

四.键盘返回值介绍:

键盘的处理器如果发现有键被按下或释放将发送扫描码的信息包到计算机。扫描码有两种不同的类型:通码和断码。当一个键被按下就发送通码,当一个键被释放就发送断码。每个按键被分配了唯一的通码和断码。这样主机通过查找唯一的扫描码就可以测定是哪个按键。每个键一整套的通断码组成了扫描码集。有三套标准的扫描码集:分别是第一套,第二套和第三套。所有现代的键盘默认使用第二套扫描码。
       虽然多数第二套通码都只有一个字节宽,但也有少数扩展按键的通码是两字节或四字节宽。这类的通码第一个字节总是为E0。
       正如键按下通码就被发往计算机一样,只要键一释放断码就会被发送。每个键都有它自己唯一的通码和断码。幸运的是你不用总是通过查表来找出按键的断码。在通码和断码之间存在着必然的联系。多数第二套断码有两字节长。它们的第一个字节是F0 ,第二个字节是这个键的通码。扩展按键的断码通常有三个字节,它们前两个字节是E0h,F0h ,最后一个字节是这个按键通码的最后一个字节。下面列出了几个按键的第二套通码和断码:

No.

KEY

通码(第二套)

断码(第二套)

1

"A"

1C

F0 1C

2

"5"

2E

F0 2E

3

"F10"

09

F0 09

4

Right Arrow

E0 74

E0 F0 74

5

Right "Ctrl"

E0 14

E0 F0 14

一个键盘发送值的例子:
      通码和断码是以什么样的序列发送到你的计算机从而使得字符G 出现在你的字处理软件里的呢?因为这是一个大写字母,需要发生这样的事件次序:按下Shift 键-按下G键-释放G 键-释放Shift 键。与这些时间相关的扫描码如下:Shift 键的通码12h,G 键的通码34h ,G 键的断码F0h 34h ,Shift 键的断码F0h 12h 。因此发送到你的计算机的数据应该是:

12h 34h F0h 34h F0h 12h

五:第二套扫描码:

101 102 和104 键的键盘:

KEY

通码

断码

  KEY 通码 断码   KEY 通码 断码

A

1C

F0 1C

    9 46 F0 46     [ 54 F0 54

B

32

F0 32

  ` 0E F0 0E   INSERT E0 70 E0 F0 70

C

21

F0 21

  - 4E F0 4E   HOME E0 6C E0 F0 6C

D

23

F0 23

  = 55 F0 55   PG UP E0 7D E0 F0 7D

E

24

F0 24

  \ 5D F0 5D   DELETE E0 71 E0 F0 71
F 2B F0 2B   BKSP 66 F0 66   END E0 69 E0 F0 69
G 34 F0 34   SPACE 29 F0 29   PG DN E0 7A E0 F0 7A
H 33 F0 33   TAB 0D F0 0D   U ARROW E0 75 E0 F0 75
I 43 F0 43   CAPS 58 F0 58   L ARROW E0 6B E0 F0 6B
J 3B F0 3B   L SHFT 12 F0 12   D ARROW E0 72 E0 F0 72
K 42 F0 42   L CTRL 14 F0 14   R ARROW E0 74 E0 F0 74
L 4B F0 4B   L GUI E0 1F E0 F0 1F   NUM 77 F0   77
M 3A F0 3A   L ALT 11 F0 11   KP / E0 4A E0 F0 4A
N 31 F0 31   R SHFT 59 F0 59   KP * 7C F0   7C
O 44 F0 44   R CTRL E0 14 E0 F0 14   KP - 7B F0 7B
P 4D F0 4D   R GUI E0 27 E0 F0 27   KP + 79 F0 79
Q 15 F0 15   R ALT E0 11 E0 F0 11   KP EN E0 5A E0 F0 5A
R 2D F0 2D   APPS E0 2F E0 F0 2F   KP 71 F0 71
S 1B F0 1B   ENTER 5A F0 5A   KP 0 70 F0 70
T 2C F0 2C   ESC 76 F0 76   KP 1 69 F0 69
U 3C F0 3C   F1 05 F0 05   KP 2 72 F0 72
V 2A F0 2A   F2 06 F0 06   KP 3 7A F0 7A
W 1D F0 1D   F3 04 F0 04   KP 4 6B F0 6B
X 22 F0 22   F4 0C F0 0C   KP 5 73 F0 73
Y 35 F0 35   F5 03 F0 03   KP 6 74 F0 74
Z 1A F0 1A   F6 0B F0 0B   KP 7 6C F0 6C
0 45 F0 45   F7 83 F0 83   KP 8 75 F0 75
1 16 F0 16   F8 0A F0 0A   KP 9 7D F0 7D
2 1E F0 1E   F9 01 F0 01   ] 58 F0 58
3 26 F0 26   F10 09 F0 09   ; 4C F0 4C
4 25 F0 25   F11 78 F0 78   ' 52 F0 52
5 2E F0 2E   F12 07 F0 07   , 41 F0 41
6 36 F0 36   PRNT
SCRN
E0 12
E0 7C
E0 F0
7C E0
F0 12
  . 49 F0 49
7 3D F0 3D   SCROLL 7E F0,7E   / 4A F0 4A
8 3E F0 3E   PAUSE E1 14 77
E1 F0 14
F0 77
-NONE-        

ACPI 扫描码:

KEY

通码

断码

Power

E0, 37

E0, F0, 37

Sleep

E0, 3F

E0, F0, 3F

Wake

E0, 5E

E0, F0, 5E

Windows 多媒体扫描码:

KEY

通码

断码

Next Track

E0, 4D

E0, F0, 4D

Previous Track

E0, 15

E0, F0, 15

Stop

E0, 3B

E0, F0, 3B

Play/Pause E0, 34 E0, F0, 34
Mute E0, 23 E0, F0, 23
Volume Up E0, 32 E0, F0, 32
Volume Down E0, 21 E0, F0, 21
Media Select E0, 50 E0, F0, 50
E-Mail E0, 48 E0, F0, 48
Calculator E0, 2B E0, F0, 2b
My Computer E0, 40 E0, F0, 40
WWW Search E0, 10 E0, F0, 10
WWW Home E0, 3A E0, F0, 3a
WWW Back E0, 38 E0, F0, 38
WWW Forward E0, 30 E0, F0, 20
WWW Stop E0, 28 E0, F0, 28
WWW Refresh E0, 20 E0, F0, 20
WWW Favorites E0, 18 E0, F0, 18

简单实例代码如下:

#include<REG52.h>

sbit LS138A=P2^2; 
sbit LS138B=P2^3;
sbit LS138C=P2^4;

sbit BEEP = P1^5;

sbit Key_Data = P1^6 ;   //定义键盘引脚
sbit Key_CLK = P3^2;     //使用外部中断

void Decode(unsigned char ScanCode);  //解码子程序
void delay(unsigned int i);      //函数声名
void display();
void beep();

// 此表为 LED 的字模            // 0    1    2    3    4    5    6   7    8    9    A    b    c    d    E    -    L   P    U   Hidden  _ (20)
unsigned char code Disp_Tab[] = { ~0xC0,~0xF9,~0xA4,~0xB0,~0x99,~0x92,~0x82,~0xF8,~0x80,~0x90,~0x88,~0x83,~0xC6,~0xA1,~0x86,~0xbf,~0xc7,~0x8c,~0xc1, ~0xff,  ~0xf7 };
bit BF;            
unsigned char KeyV;
unsigned char LedNumVal  ;
int KEY_val,IntNum;

void main()
{

IT1 = 0;                              //设外部中断1为低电平触发
EA = 1;                               //外部中断开
EX0 = 1;                              //开中断

while(1)
{
   if (BF)
    { 
if (KeyV != 240)  beep(); 
  
       Decode(KeyV); //解码
   
   }
    else
      EA = 1; //开中断 
   display();
}

}

void Keyboard_out(void) interrupt 0
{
if ((IntNum > 0) && (IntNum < 9))
   {
KeyV = KeyV >> 1;                //因键盘数据是低>>高,结合上一句所以右移一位
if (Key_Data)
     KeyV = KeyV | 0x80;          //当键盘数据线为1时到最高位
}
IntNum++;
while (!Key_CLK);                //等待PS/2CLK拉高

if (IntNum > 10)
    {
   IntNum = 0;                  //当中断11次后表示一帧数据收完,清变量准备下一次接收
   BF = 1;                      //标识有字符输入完了
  EA = 0;                      //关中断等显示完后再开中断
  }

}

void Decode(unsigned char ScanCode) //注意:如SHIFT+G为12H 34H F0H 34H F0H 12H,也就是说shift的通码+G的通码+shift的断码+G的断码
{
   
   switch (ScanCode)
   {
   case 0x70 :             // 当收到0xF0,Key_UP置1表示断码开始
    KEY_val = 0;
    break;

case 0x69 :            
    KEY_val = 1;
    break;

case 0x72 :            
    KEY_val = 2;
    break;

case 0x7A :            
       KEY_val = 3;
    break;

case 0x6B :            
    KEY_val = 4;
    break;

case 0x73 :            
    KEY_val = 5;
    break;

case 0x74 :            
    KEY_val = 6;
    break;

case 0x6c :            
    KEY_val = 7;
    break;

case 0x75 :            
    KEY_val = 8;
    break;

case 0x7d :            
    KEY_val = 9;
    break;

case 0x71 :
                 
   // dot = 0X7F;
    break;

}
 
 
BF = 0; //标识字符处理完了 
}

void display( )
{
   unsigned char i;
   unsigned int LedOut[8];

LedNumVal = KEY_val ;

LedOut[0]=Disp_Tab[LedNumVal000/1000];
     LedOut[1]=Disp_Tab[LedNumVal00/100];
     LedOut[2]=Disp_Tab[LedNumVal0/10];
     LedOut[3]=Disp_Tab[LedNumVal];
 
  LedOut[4]=Disp_Tab[LedNumVal000/1000];    //千位
     LedOut[5]=Disp_Tab[LedNumVal00/100];  //百位带小数点
     LedOut[6]=Disp_Tab[LedNumVal0/10];     //十位
     LedOut[7]=Disp_Tab[LedNumVal];             //个位

for( i=0; i<8; i++)
  {  P0 = LedOut[i];
  
   switch(i)      
      {    
   case 0:LS138A=0; LS138B=0; LS138C=0; break;        
         case 1:LS138A=1; LS138B=0; LS138C=0; break;             
         case 2:LS138A=0; LS138B=1; LS138C=0; break;
         case 3:LS138A=1; LS138B=1; LS138C=0; break;
   case 4:LS138A=0; LS138B=0; LS138C=1; break;
   case 5:LS138A=1; LS138B=0; LS138C=1; break;
   case 6:LS138A=0; LS138B=1; LS138C=1; break;
   case 7:LS138A=1; LS138B=1; LS138C=1; break;
  
      }
  
  delay(50);
   }

}

void delay(unsigned int i)
{
    char j;
    for(i; i > 0; i--)
        for(j = 200; j > 0; j--);
}

void beep()
{
  unsigned char i;
  for (i=0;i<255;i++)
   {
   delay(5);
   BEEP=!BEEP;                 //BEEP取反
   }
  BEEP=1;                      //关闭蜂鸣器
}

PS2接口协议及代码分析相关推荐

  1. OpenAVNU 带宽预留协议SRP代码分析

    OpenAVNU 带宽预留协议SRP代码分析 AVNU AVNU由专业的汽车,消费电子和工业制造公司组成的联盟,它们共同致力于建立开放AVB和TSN标准的互操作性的认证. OpenAVNU AVNU在 ...

  2. ISIS协议和代码分析

    ISIS与OSPF相似,内核算法基于SPF ISIS可扩展性良好,源于其报文的TLV定义 ISIS层次划分清晰,L1,L2对路由的获取层级不同. ISIS协议部分DR选举较OSPF确定. quagga ...

  3. sas协议内核代码分析

    1.sas相关对象 (1)所有关于sas头文件,所涉及的对象和枚举 kernel/include/scsi/libsas.h kernel/include/scsi/scsi_transport_sa ...

  4. android蓝牙hid 鼠标,BLE HID协议-----蓝牙鼠标代码流分析

    隐藏了蓝牙 写在前面: 使用SDK版本NRF 12.3.0, nRF52 \ nRF52832包\ nRF5_SDK_12.3.0_d7731ad \ examples \ ble_periphera ...

  5. BT源代码学习心得(七):跟踪服务器(Tracker)的代码分析(HTTP协议处理对象) -- 转贴自 wolfenstein (NeverSayNever)

    BT源代码学习心得(七):跟踪服务器(Tracker)的代码分析(HTTP协议处理对象) author: wolfenstein (NeverSayNever) 上次我们分析了Tracker类初始化的 ...

  6. 基于FPGA的UART接口协议设计

    一.PC终端概述 PC终端,Personal Computer 智能终端,通俗的讲,就是利用电脑GUI界面控制我们的外部硬件电路. 因此设计到了PC与外部硬件电路的通信接口.对于台式电脑.个人笔记本, ...

  7. Linux内核中的GPIO系统之(3):pin controller driver代码分析

    一.前言 对于一个嵌入式软件工程师,我们的软件模块经常和硬件打交道,pin control subsystem也不例外,被它驱动的硬件叫做pin controller(一般ARM soc的datash ...

  8. 完整全面的Java资源库(包括构建、操作、代码分析、编译器、数据库、社区等等)...

    构建 这里搜集了用来构建应用程序的工具. Apache Maven:Maven使用声明进行构建并进行依赖管理,偏向于使用约定而不是配置进行构建.Maven优于Apache Ant.后者采用了一种过程化 ...

  9. AUTOSAR从入门到精通100讲(三十五)-Lin通信协议栈分析三部曲LinTrcv配置及代码分析

    LinTrcv 0.Lin通信协议栈简介: LIN通信服务是一组用于与LIN通信系统进行车辆网络通信的模块.提供统一的LIN网络接口.对应用层程序隐藏协议信息和消息属性的特性. Lin通信服务包括: ...

最新文章

  1. 专业写博一天------ArrayList 线程安全
  2. C#中 ??、 ?、 ?: 、?.、?[ ] 问号
  3. 6-3 求链表的倒数第m个元素
  4. C#中泛型的相关知识点总结
  5. Spring回滚事务类型
  6. 前端学习(1747):前端调试值之console用处
  7. Android 循环滚动控件ViewFlipper,可实现跑马灯或轮播图效果
  8. echarts我常用的参数总结
  9. AcWing 1987. 粉刷栅栏(离散化+差分)
  10. matlab股票数据画图,matlab股票数据接口(一)
  11. 为SM30视图创建TCODE
  12. 263企业邮箱服务器是什么,千万别用263企业邮箱 - 外贸邮箱邮件群发 - 电脑网络 - 福步外贸论坛(FOB Business Forum) |中国第一外贸论坛...
  13. 千呼万唤始出来——DataV私有部署功能
  14. 1039:判断数正负(测试已通过)
  15. edge播放视频HTML5黑屏,Win10 edge浏览器播放视频黑屏解决方法
  16. 【git安装、使用、常用命令】
  17. 什么是Eclipse RCP?
  18. 目标追踪与定位学习笔记8-排斥损失:检测人群中的行人
  19. 分布式服务器时间同步
  20. linux中文写作软件,码字写作软件下载 极音创作(码字软件)V1.3.5 linux版 下载-脚本之家...

热门文章

  1. 这些夕阳产品的编程语言即将死去,有你学的吗?
  2. web编程期中项目作业
  3. Windows下命令行怎样登录MySQL
  4. H3C交换机配件RS232配置线(DB9针转RJ45) 1
  5. windows的局域网渗透
  6. 中关村“染指”番茄花园
  7. python 发送邮件535, 'Error: authentication failed' 解决
  8. eclipse中的buidpath配置(工程不build)
  9. The Shawshank Redemption-6
  10. API网关之Kong初识