分享

为什么 USB 键盘会有键冲而 PS2 的键盘却能全键无冲?

 金刚光 2023-11-08 发布于辽宁

 47,255

6 个回答

小大熊猫
man in the mirror

水平有限,如有错误还请指正。

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键盘,控制器还会通过与之前的状态进行比较,确定按键是被按下还是被释放,从而将相应的按键扫描码发送给主机。

编辑于 2023-10-16 20:40・IP 属地北京
胡莉彤
CRH2G-0001专属铁路人偶,现已支持USB PPS(雾

太长不看版:请先问是不是[1] [2]再问为什么。理论上USB键盘一样可以做到全键无冲(并不使用额外的驱动程序等),但在部分品牌电脑(如惠普、苹果)[3]的固件内可能无法正常使用。


IBM F62 复刻版镇楼。

理论上而言,USB 人体学输入设备(即键盘、鼠标等设备)所遵循的技术规范本身允许外设采用自定义报文格式并将报文结构通过“HID 描述符”传递给主机。在此条件下,键盘固件编写者完全可以通过在报文内声明一个很长的位段或者类似的手段来向主机传递所有键位的状态。但是,对于电脑本身的固件(比如 PC BIOS)的编写者而言,解析 HID 描述符并且完整支持 HID 规范则过于复杂了。因此,USB HID 规范针对键盘规定了一个易于解析的报文格式[1]

  1  ui  Bitfield of Modifier Keys (LCtrl, RCtrl, LShift, RShift, LAlt, RAlt, LWindows, RWindows)
  1  ui  Reserved (0)
  1  ui  Scancode 1 (or 0)
  1  ui  Scancode 2 (or 0)
  1  ui  Scancode 3 (or 0)
  1  ui  Scancode 4 (or 0)
  1  ui  Scancode 5 (or 0)
  1  ui  Scancode 6 (or 0)

这个简易报文(也就是其他答主提到的“USB 协议”)可以在修饰键外支持最多六个额外的按键,而大部分中低端 USB 键盘也仅支持该报文。故此类键盘即使硬件上支持全键无冲(如静电电容键盘),也仅支持最多六个按键。

而对于物理上支持全键无冲的键盘而言,理论上键盘本身只需向主机枚举两个虚拟 HID 设备(一个遵循简易协议的基本键盘、一个采用自定义报文格式的全功能厂商定义设备)即可支持原生全键无冲。可惜,包括 Windows 在内的主流操作系统在检测到此类设备时,会读取基本键盘设备而无视厂商定义设备,导致全键无冲无法正常工作[1]。对于该问题的一个常见的解决方案是由厂商编写自定义键盘驱动,在驱动层面上屏蔽基本键盘设备而强制使用厂商定义的设备。

除此之外,还有一个有滥用 HID 协议的嫌疑的思路:利用大部分电脑固件并不会去解析 HID 描述符而是直接按照约定俗成的简易报文格式直接读取键盘报文的特点,令一块采用自定义报文的键盘也能向下兼容简易报文[1]

  1  ui  Bitfield of Depressed Modifier Keys (LCtrl, RCtrl, LShift, RShift, LAlt, RAlt, LWindows, RWindows)
  1  ui  Padding
  1  ui  "Padding" (actually: Scancode 1)
  1  ui  "Padding" (actually: Scancode 2)
  1  ui  "Padding" (actually: Scancode 3)
  1  ui  "Padding" (actually: Scancode 4)
  1  ui  "Padding" (actually: Scancode 5)
  1  ui  "Padding" (actually: Scancode 6)
 13  ui  Bitfield of Depressed Non-Modifier Keys

在该实现中,键盘向主机只枚举一个“厂商定义设备”,并且 HID 描述符声明了一部分格式与简易报文吻合的“占位符”。而实际上,报文的前 8 位是按照简易报文规范编码的一部分按键键码信息。电脑固件在遇到该报文时,由于一般会无视 HID 描述符直接按照简易报文格式解析,将会正确解析出简易报文部分的内容;而进入操作系统以后,操作系统则会根据 HID 描述符的内容,忽略被声明为占位符的简易报文内容,从而支持全键无冲。目前已知采取该技巧实现无驱动支持全键无冲的键盘包括 MODEL F LABS 复刻的 Model F 静电屈蹲弹簧键盘(ibm-capsense-usb[2]固件默认支持;QMK 固件需要手动启用[3])以及改装了 xwhatsit 主板的 IBM 原厂古董键盘(Model F 以及更古老的 DisplayWriter 等)[2]

不过这种投机取巧的思路也有缺点:有一部分没有完整实现 USB HID 标准的电脑固件(如苹果以及惠普的固件)可能会直接无视采用这种报文格式的键盘,因此 Model F Labs 在其采用的 QMK 固件中默认关闭了全键无冲模式[3]。并且笔者的确在自己的惠普 EliteBook 745 G6 上遇到了与 xwhatsit 固件相关的开机阶段键盘无法使用的问题(在刷入 QMK 固件并且保持全键无冲模式关闭后得到了解决)。

综上所述,USB 键盘在理论上并没有实现全键无冲的技术障碍;而厂家选择不直接实现全键无冲则更多是因为协议本身的历史遗留所导致的兼容性问题(中高端产品)或成本考虑(低端产品)。

参考

  1. ^abcdhttps://www./~hl/usbnkro
  2. ^abchttps://static./ibm-capsense-usb-web/ibm-capsense-usb.html#x1-160003.3.2
  3. ^abchttps://www./manual/
先谢郭嘉
有情调的送礼达人,兢兢业业的测评人(合作看简介)

因为在USB的协议下,定期向主机发送当前按键的状态,每次只能发送8个字节。

第一个就是左右的Ctrl、Shift、Alt、Win这些按键有没有被按下,键盘上的这8个键的状态就由这一个字节表示。

第二个保留(没用)

还剩下6个字节,就对应着按下的6个按键,数字键、字母等。要是一次性按键超出了6个,那么会自动选取前6个或者后6个。

所以一次性最多是可以发送14个按键的信息的。其实USB接口的伪无冲对日常的应用影响不大,毕竟就10根手指头,全键无冲对于平常人来说用处真的不是很明显。PS/2接口还有一个比较遗憾的问题,PS/2接口的键盘都是薄膜键盘,只能实现局部的无冲。现在还是USB接口的主流,并且PS/2的电器安全性和可靠性受到设计因素的影响不小。其实就算有无冲的机械键盘,还是USB接口好一点。

 匿名用户

匿名用户

两个因素:硬件和软件。

软件上,USB键盘的HID报文为了兼容和方便老旧BIOS去解析,只能采取比较简短的格式,这个格式的长度只能装6个键。但是一旦进入了操作系统就能加载专门解析报文的驱动,100个键无冲都没问题。合格的键盘可以切换模式(模式由计算机主动申请,是HID协议标准支持的),便宜货就只支持6键的了。此外,不需要模拟多个键盘,不需要特殊驱动(3大操作系统都能解析)

硬件上,键盘的按键扫描为了成本,普遍采用矩阵扫描。固有缺点是会产生鬼键(如果按下直角上的3个按钮,则对面的第4个按钮也会触发),软件要消除这个影响,固然做不到全键无冲。

(不想细究的,可以看稚晖君键盘那一期视频)

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多