水平有限,如有错误还请指正。
PS/2是一种双向同步串行通讯协议,PS/2键盘的时钟信号频率通常在10-20kHz之间。PS/2按键扫描码存在通码和断码两种。当检测到某个按键被按下,键盘会向主机发送该按键对应的通码。如果有一个按键被持续按下没有释放,键盘会不断向主机发送该按键对应的通码。如果有多个按键同时被持续按下没有释放,键盘会不断向主机发送最后一个被检测到的按键对应的通码。当检测到某个按键被释放,键盘会向主机发送该按键对应的断码。
可以看出,由于采用串行通讯,在接口层面上,PS/2实现全键盘任意按键无冲突没有瓶颈。
USB HID采用的是报文形式,USB键盘的轮询率通常是125Hz,每次向主机发送8字节的报文。USB HID的扫描码没有通码和断码之分,每次发送的数据标识当前有哪些按键被按下。当按键被释放,在下一个报文中该按键对应的扫描码就会被移除。
USB键盘报告的第1字节用于标识左右Ctrl、Shift、Alt和Win键是否按下,第2字节保留,第3至8字节用于标识普通键是否按下,每个字节只能标识一个普通键。因此,标准的USB键盘只能支持任意6键同时按下无冲突,最多14键同时按下无冲突。
可以看出,由于USB HID的限制,USB键盘无法直接实现全键盘任意按键无冲突。为了解决这一问题,键盘制造商采取了一系列手段,如将单个USB键盘虚拟成多个USB HID设备和自定义USB HID报文格式等。不过有时自定义USB HID报文格式的USB键盘会遇到兼容性问题,如在某些主板BIOS界面下无法使用键盘等。
至于键盘内部的按键冲突,来源于矩阵按键扫描时电流逆流导致的“幽灵按键”现象。薄膜键盘的应对办法是优化布线,尽可能避免可能同时按下的按键冲突。当然这只能缓解冲突并不能解决冲突,为了避免出现“幽灵按键”现象,键盘控制器只能屏蔽其中部分按键。机械键盘通常采取在每个按键处都设置二极管的办法来避免这个问题。
实际上键盘中的按键是被设置在一个矩阵中的,这个矩阵由许多列线(输入)和行线(输出)构成,列线和行线交叉处就是按键开关。在没有按键触发时,行线和列线之间彼此断开。所有列线均置为高电平,而行线则会根据扫描情况发生变化。
当控制器进行扫描时,将所有行线设置为低电平,然后检测列线,如果有列线为低电平则说明有按键闭合。随后控制器将所有行线设置为浮空,依次将行线逐行设置为低电平(其余行线浮空),并读取所有列线的情况。当读取到低电平的列线时,列线和行线交叉处的按键就是被闭合的按键,控制器通过查表即可得知结果。
以上图为例,1和2为列线,3和4为行线。检测按键时分别向行线3和4加低电平。当W键被按下,对3加低电平时,2会被拉低,控制器通过查表可以得知此时W键被按下。
这里可能会遇到一种情况:当QWA键被同时按下时,对4加低电平会导致一部分电流通过W(向下)、Q(向上)、A(向下)键从4流出,导致2被拉低,从而导致控制器认为S键也被按下,这就是“幽灵按键”。要避免“幽灵按键”的出现,比较简单粗暴的办法是当按下相邻4个键中的2个键后,便屏蔽其它2个按键,虽然这会导致无法同时识别矩阵中相邻的部分按键,但是这种情况通常非常少见。为了缓解“幽灵按键”导致的按键冲突,可以采取优化键盘布线的办法,将可能同时按下的按键尽可能分布在不同的行列上,从而减少按键冲突的发生。要完全避免“幽灵按键”和其导致的按键冲突,可以在每个按键处都设置一个二极管,只允许电流单向通过(向下),这一问题就得到了解决。通常机械键盘会采用这种解决办法,而薄膜键盘出于成本和定位考虑不会这样做。
键盘控制器不断扫描整个矩阵,当检测到按键触发时,控制器会将其转换为键盘码值并存储在特定的寄存器中。每隔一段时间,控制器会查询寄存器中的数据,将其编码为报文,通过外部总线发送给主机。对于PS/2键盘,控制器还会通过与之前的状态进行比较,确定按键是被按下还是被释放,从而将相应的按键扫描码发送给主机。