PS/2 键盘:设备供时钟的双向同步串口
更新时间:2026-09-12。本文是「集成电路大类 · 芯片设计」**入门层(beginner)**数字逻辑基础第八十四篇。UART是双方各备时钟的异步串口,PS/2 正好相反——时钟由键盘提供、数据在时钟沿上走,而且方向可反转为主机发命令。它非常适合用来理解「时钟由谁供」「双向总线仲裁」和「带校验的定长帧」。
本文要回答的问题
- 11 位帧的起始/数据/校验/停止怎么排?数据位先发哪一端?
- 主机在时钟的哪个沿采样才不会踩在跳变中间?
- 通码、断码、0xF0、0xE0 分别表示什么?长按发生什么?
- 主机想点亮 Caps Lock 灯,怎么反过来占用总线发命令?
- 收到帧后用奇校验怎么发现传输出错?
一、物理层:两根开漏线,设备主导时钟
PS/2 只有 CLK 和 DATA(加电源地),两线都是集电极开路、靠上拉为高,任一方可拉低(与 1-Wire 线与思想相同,但有时钟)。通信时通常由键盘产生约 10~16.7kHz 的时钟,数据在 CLK 的下降沿稳定、由主机在下降沿采样(也可理解为设备在下降沿更新、主机在低电平期间读取)。因为时钟来自设备,主机本质是接收方,不需要自己的波特率发生器,只要用本地高频时钟去检测 PS/2 时钟的下降沿即可(边沿检测/同步器,CLK 虽慢但仍属异步输入)。
二、11 位帧:起始 + 8 数据 + 奇校验 + 停止
起始(0) D0 D1 ... D7 奇校验P 停止(1)
└────── LSB 先发 ──────┘
每个位持续一个 CLK 周期,主机在 CLK 下降沿采样 DATA- 起始位固定 0、停止位固定 1,用于帧定界;
- 8 个数据位 LSB 先发(和 I2S/UART 一样从低位进移位寄存器);
- 奇校验位:8 个数据位连同校验位中 1 的总数为奇数,收方数 1 的个数不对即丢弃该帧;
- 用一个 11 状态的移位状态机按下降沿逐位装入、在停止位把拼好的字节和有效标志交给上层即可。
三、通码与断码:按下、松开、扩展、自动重复
采用 scan code set 2(最常用):每个键有**通码(make)**表示按下、**断码(break)**表示松开。多数普通键断码 = 在通码前加前缀 0xF0(如字母 A 通码 0x1C、断码 F0 1C);特殊/扩展键(方向键、右 Ctrl、Insert 等)在码前再加 0xE0。按住不放时键盘只反复发通码(typematic 自动重复),不发断码,直到松开才发一个 F0+通码——所以上层要用「收到通码置按下、收到 F0 后下一字节清按下」的状态机维护按键状态。这和矩阵键盘输出的是「物理行列/扫描码」而非 ASCII 一致,字符映射交给上层。
四、主机→设备:申请总线再让设备供时钟
要点亮 Caps/Num/Scroll Lock 灯,主机要反向发送:
- 主机把 CLK 拉低约 100µs(请求占用总线,设备看到后停止驱动时钟);
- 主机把 DATA 拉低(这是起始位)后释放 CLK;
- 设备接管并开始产生时钟,主机在设备时钟下逐位输出 8 数据(LSB 先)、奇校验、停止位,设备在时钟上升沿采样;
- 设备收完后把 DATA 拉低一个时钟周期回送 0xFA 应答(ACK)。
LED 命令是一个固定字节(0xED)后跟一个 3bit 掩码(Scroll/Num/Caps)。这体现了双向开漏总线的方向仲裁:想说话的一方先把线拉低来申请,另一方配合提供时钟。
五、接收侧实现要点
- CLK/DATA 都先进两级同步器(设备时钟相对主机异步),再对同步后的 CLK 做下降沿检测得到一次采样脉冲(同步+边沿检测的标准用法);
- 在该脉冲上把 DATA 移入 11 位移位寄存器并对位数计数,第 10 位(校验)检查「起始为 0、8 数据+校验共含奇数个 1、停止为 1」,通过才输出字节和 valid/dav 脉冲;
- 检测到 0xF0/0xE0 前缀时连同下一字节一起交给上层译码;帧错则丢弃并复位帧状态机。时钟只有十几 kHz,用几十 MHz 系统时钟去过采样绰绰有余。
与现有篇目的衔接
总结
一句话总结:PS/2 是只有 CLK 和 DATA 两线、均为开漏上拉的双向同步串行口,通常由键盘提供约 10~17kHz 时钟,一帧固定 11 位——起始位 0、8 个数据位(LSB 先发)、1 个奇校验位、停止位 1,设备在时钟下降沿更新数据、主机在下降沿附近采样,接收端把异步的 CLK/DATA 先两级同步再做下降沿检测,在每个采样脉冲移入一位并用 11 状态移位状态机拼帧,同时校验起始为 0、停止为 1、8 数据加校验含奇数个 1,出错即丢帧;按键语义上,set 2 扫描码用通码表示按下、在通码前加 0xF0 表示松开,扩展键再加 0xE0 前缀,按住只重复发通码直到松开才发断码,上层据此维护按下/释放状态,扫描码到字符的映射与矩阵键盘一样交给软件;反向控制(如点亮大小写灯)时主机先拉低 CLK 约 100µs 申请总线、再拉低 DATA 作起始位并释放 CLK,由设备产生时钟、主机逐位发送并由设备回送 0xFA 应答,体现了开漏双向总线靠主动拉低完成的方向仲裁,与无时钟的 UART 和单线 1-Wire 形成清晰对照。