【PC端】 :
从我前面转载的一篇文章<PC常用的I/O地址 (转)>可以知道:
pc机上对键盘进行读写与控制的io端口是60H和64H.
60H作为数据端口,由改端口可以给键盘写数据或读取键盘数据
64H作为命令端口,可以读取键盘的状态或写入命令数据
【键盘控制器端】 :
在linux下我们可以用下面的命令来查看我们pc机当前使用的是什么键盘控制器:
helight@helight-desktop:~$ cat /proc/interrupts
14:
15:
......
另外键盘一般使用的中断号是1.所以可以看出其对应的控制器是i8042,当然从网上查了资料得知,一般情况下的键盘
控制器也就是i8042,所以看到这两个都有时,就可以确定键盘中断号是1,键盘控制器就是i8042.
i8042:
i8042也就是intel8042,位于主板上,CPU通过IO端口与i8042通信,i8042则负责读取键盘按键的扫描吗或是发送个中键盘命令.另外还有一个芯片是8048,它是位于键盘中的,是将键盘上的按键转换成所谓的扫描码,关于扫描码下面会做简单的介绍.
而我们的键盘驱动直接读写 i8042 芯片,通过 i8042 间接的向键盘中的 i8048 发命令。所以对于驱动来说,直接发生联系的只有 i8042 ,因此我们只介绍 i8042 ,不介绍 i8048。
i8042有四个8bits的寄存器,他们是状态机存器,输出寄存器,输入寄存器和控制寄存器.而端口只是用60H和64H两个端口.
状态寄存器是一个8位只读寄存器,任何时刻均可被cpu读取。其各位定义如下
Bit7: PARITY-EVEN(P_E): 从键盘获得的数据奇偶校验错误
Bit6: RCV-TMOUT(R_T): 接收超时,置1
Bit5: TRANS_TMOUT(T_T): 发送超时,置1
Bit4: KYBD_INH(K_I): 为1,键盘没有被禁止。为0,键盘被禁止。
Bit3: CMD_DATA(C_D): 为1,输入缓冲器中的内容为命令,为0,输入缓冲器中的内容为数据。
Bit2: SYS_FLAG(S_F): 系统标志,加电启动置0,自检通过后置1
Bit1: INPUT_BUF_FULL(I_B_F): 输入缓冲器满置1,i8042 取走后置0
BitO: OUT_BUF_FULL(O_B_F): 输出缓冲器满置1,CPU读取后置0
Output Buffer(输出缓冲器)
输出缓冲器是一个8位只读寄存器。驱动从这个寄存器中读取数据。这些数据包括,扫描码,发往 i8042 命令的响应,间接的发往 i8048 命令的响应。
Input Buffer(输入缓冲器)
输入缓冲器是一个8位只写寄存器。缓冲驱动发来的内容。这些内容包括,发往 i8042 的命令,通过 i8042 间接发往 i8048 的命令,以及作为命令参数的数据。
Control Register(控制寄存器)
也被称作 Controller Command Byte (控制器命令字节)。其各位定义如下
Bit7: 保留,应该为0
Bit6: 将第二套扫描码翻译为第一套
Bit5: 置1,禁止鼠标
Bit4: 置1,禁止键盘
Bit3: 置1,忽略状态寄存器中的 Bit4
Bit2: 设置状态寄存器中的 Bit2
Bit1: 置1,enable 鼠标中断
BitO: 置1,enable 键盘中断
【控制命令】 :
对键盘的控制命令有两种:
1.使用于i8042的命令,这种命令是直接写给i8042来完成.
这一类的操作有:给i8042写命令或读命令,设置键盘密码,自检,开启或禁用键盘等.
常用命令:
驱动对键盘控制器发送命令是通过写端口64h实现的,共有12条命令,分别为
20h
准备读取8042芯片的Command Byte;其行为是将当前8042 Command Byte的内容放置于Output Register中,下一个从60H端口的读操作将会将其读取出来。
60h
准备写入8042芯片的Command Byte;下一个通过60h写入的字节将会被放入Command Byte。
A4h
测试一下键盘密码是否被设置;测试结果放置在Output Register,然后可以通过60h读取出来。测试结果可以有两种值:FAh=密码被设置;F1h=没有密码。
A5h
设置键盘密码。其结果被按照顺序通过60h端口一个一个被放置在Input Register中。密码的最后是一个空字节(内容为0)。
A6h
让密码生效。在发布这个命令之前,必须首先使用A5h命令设置密码。
AAh
自检。诊断结果放置在Output Register中,可以通过60h读取。55h=OK。
ADh
禁止键盘接口。Command Byte的bit-4被设置。当此命令被发布后,Keyboard将被禁止发送数据到Output Register。
AEh
打开键盘接口。Command Byte的bit-4被清除。当此命令被发布后,Keyboard将被允许发送数据到Output Register。
C0h
准备读取Input Port。Input Port的内容被放置于Output Register中,随后可以通过60h端口读取。
D0h
准备读取Outport端口。结果被放在Output Register中,随后通过60h端口读取出来。
D1h
准备写Output端口。随后通过60h端口写入的字节,会被放置在Output Port中。
D2h
准备写数据到Output Register中。随后通过60h写入到Input Register的字节会被放入到Output Register中,此功能被用来模拟来自于Keyboard发送的数据。如果中断被允许,则会触发一个中断。
2.以数据的形式写给i8042,再由i8042以命令的形式写给i8048达到控制目的.
这一类的操作有: 设置LED灯设置键盘的扫描码类型,设置键盘的工作方式等.
【扫描码】 :
当键盘上有键被按下,松开,按住,键盘将产生扫描码( Scan Code ),这些扫描码将被 i8048 直接得到。扫描码有两种,Make Code 和 Break Code。当一个键被按下或按住时产生的是 Make Code ,当一个键被松开产生的是 Break Code。每个键被分配了唯一的 Make Code 和 Break Code ,这样主机通过扫描码就可以知道是哪一个键。简单的说就是按下键,产生一个 Make Code。松开键,产生一个 Break Code。
到目前为止一共有三套扫描码集( Scan Code Set ),ps/2 键盘默认使用第二套。不过可以设置 i8042,让 i8042 把得到的 Scan Code 翻译成 Scan Code Set 1 中的 Scan Code ,这样键盘驱动从 i8042 得到的所有 Scan Code 都是第一套中的 Scan Code(实际中驱动也是这么做的)。所以我们只讨论 Scan Code Set 1 。需要说明的是 Scan Code 和 ASCII码完全不相同。
在 Scan Code Set 1 中,大多数键的 Make Code,Break Code 都是一个字节。他们的 Make Code 的最高位都为0,也就是他们的 Make Code 都小于 0x7F。而他们的 Break Code 为其 Make Code 或运算 80h ,也就是把 Make Code 的低7位不变,最高位设置为1。
还有一些扩展按键,他们的 Scan Code 是双字节的。他们的第一个字节都是E0h,表明这是一个扩展键。第2个字节,和单字节 Scan Code 的情况相同。
还有一个特殊的键,Pause/Break 键,它的 Make Code 为 E1,1D,45 E1,9D,C5,注意是 E1h 开头。而且它没有 Break Code 。
但是经我测试,我的键盘使用的是Scan Code Set 1.
http://hi.baidu.com/wangjianzhong1981/blog/item/52f23ec3ac0af253b219a86c