笔记本电脑的键盘学习教程

描述

笔记本电脑的内置键盘是不可缺少的输入设备,它经历了二十几年的迭代才形成如今的设计标准(Key Layout、Connector、Protocol、ScanCode...)。

在键盘的发展历程中,出现了很多标准,有一些标准至今仍被使用。有兴趣可以查阅 键盘的发展。接下来就详细了解下笔记本电脑的键盘。

01—Scan Code

电脑键盘一般有 80-120 个按键,因此采用矩阵设计可以减少GPIO 的使用。

如下示意图,MCU 控制 “A/B/C/D” 都保持低电平,然后挨个输出高电平,每次输出高电平的同时采集“1/2/3/4” 电平。此过程称之为 “键盘扫描”。

如果 C-3 按键按下,当 MCU 在 “C” 列输出高电平时,在 “3” 行可检测到高电平。如此 MCU 即可判断出哪个按键被按下了。

MCU 判断出哪个按键被按下,需要以数据的形式传递给 Host 使用。因此需要给每一个按键安排一个编码,这个编码就是 ScanCode,即 “扫描码”。

这个 MCU 负责扫描矩阵,称之为 KSC(Keyboard Scan Controller)。使用最为广泛的型号是 Intel 8048。

mcu

键盘的发展历程中,一共出现过 3 套 ScanCode。

Scan Code Set-1

1983年随 IBM Personal Computer XT(XT:eXtended Technology,Type:5160) 一起发布的 XT Keyboard 就使用的是此套扫描码。当时配套的操作系统可以直接识别此套扫描码。如今的 Windows、Linux 系统都在沿用。

ScanCode Set-2

1984年随 IBM Personal Computer AT(AT:Advanced Technology,Type:5170)一起发布的 AT Keyboard 就是使用的是此套扫描码。但是操作系统并没有兼容识别此套扫描码,而是在主板上增加了一个 MCU 把 Set-2 翻译成 Set-1,然后再发送给系统。当然也有操作系统也可以识别 Set-2,但并不是主流。

新增的 MCU 称之为 KBC(Keyboard Controller),使用最为广泛的型号是 Intel 8042,因此 i8042 也用来代指 Keyboard Controller。

ScanCode Set-3

1986年,IBM 重新设计了键盘布局,在美国市场上推出了 MF2 Keyboard,有 101个按键。

MF2 Keyboard 设计上增加了逻辑更为合理的 ScanCode Set-3,由 i8042 翻译成 ScanCode Set-1 传递给 CPU。此套扫描码并未流行。

最后流行的 PS/2 键盘,采用的仍旧是 ScanCode Set-2。

02—Key Number

在 MF2 键盘出现后,键盘 Layout 基本即保持一致了,但是按键的丝印却是千变万化,不同丝印的键盘是为了满足不同语种的需求。

键盘设计中,一个按键会规定一个 ScanCode。系统端根据接收的 ScanCode 就知道是哪个按键触发了。同样是按键 “Q” 触发,系统端最终识别的字符可不一定是字符 “Q”,这是要根据系统语言判断的。

键盘语种不同,丝印就不同。因此每个按键还规定了一个 Key Number,以便区分按键。

mcu

一般键盘制造商生产的矩阵键盘,会配套一份设计图纸,会指明按键在矩阵中的位置,此时使用的就是 KeyNumber。

KSC 扫描这个矩阵,根据扫描结果,识别出触发按键在矩阵的位置,

先找到 KeyNumber,从而查找出 ScanCode。

mcu

03—Keyboard Protocol

XT Keyboard 和 AT Keyboard 的设计中,同 PCH 通讯的规范已经不再使用,因此此处只针对 PS/2 Keyboard 做描述。

PS/2 Keyboard 设计中,采用 KSC (Keyboard Scan Controller) 扫描键盘矩阵,按键触发后会编码出 ScanCode Set-2 发送。其中 KSC 是一个位于键盘内部的 MCU,以 Intel 8048 最为典型。KSC 和 KBC 之间通过 PS/2 协议通讯,完成KeyCode、Command 的传递。

PS/2 键盘结构

在 x86 CPU 系统中,有一个独立的 IO 寻址空间,大小 64K。随着计算机的发展,默认 60/64 两个 IO 地址被用作 PCH 和 KBC(i8042) 交换数据。

有以上两个通讯的支持, PS/2 Keyboard 外接在电脑 PS/2 接口上后就可以工作了。

mcu

设计框图如下

mcu

KBC 寄存器

i8042 作为一个 KBC 使用 IO 60、64 和 PCH 传递数据。

IO 60/64 分别定义为数据寄存器和状态寄存器。

针对 Status Register,在 Intel 8042 DataSheet 中定义如下。

mcu

BIT0:指示 KBC 是否在 Output Data Register 写入了数据。

BIT1:指示 CPU 是否在 Input Data Register 写入了数据。

BIT2:指示 CPU 是否读取了 Output Register。

BIT3:指示 CPU 写了 60H 还是 64H。

BIT4-7:用户自定义。

不同厂家在后续的 KBC 设计中,增加了一些自定义状态。

如下图所示,KBC 中增加了针对 PS/2 通讯状态的一些定义。

mcu

mcu

如上图,Host 端的 Keyboard Driver 利用 IO 60/64 和 KBC通讯。

KBC 内部有两个数据寄存器,Input and Output Data Register。

一个状态寄存器,Status Register。

KB Driver 写 60H 或者 64H,都对应 KBC 内部 Input Register,KBC 内部的 Status Register BIT3 会做出区分。

KB Driver 写 60H,KBC 认为是 Data。

KB Driver 写 64H,KBC 认为是自己的 Command。

KB Driver 读 60H,KBC 返回 Output Register 内容,主要是 ScanCode。

KB Driver 读 64H,KBC 返回 Status Register 内容,指示 Keyboard 状态。

04—Keyboard Command

KBC 和 KSC 作为 MCU,分别设计了一组命令。Keyboard Driver 可以发送这些命令,从而控制 KBC 和 KSC 的一些行为。

05—EC Keyboard

在上世纪的个人电脑设计中,PS/2 键盘属于一个外接设备。PS/2 键盘通过 PS/2 接口和主板上 KBC 通讯。KBC 在 PCH 和键盘中间作为一个 SuperIO 设备,管理 PS/2 键盘。

随着个人电脑的不断发展,逐渐演变出便携式电脑,即笔记本电脑。键盘作为笔记本电脑的标配输入设备,也遵守了 PS/2 键盘系统的大部分标准,并且沿用至今。

在如今的笔记本电脑设计中,不再有独立的 KSC(i8048,键盘扫描器)和 KBC(i8042,键盘控制器),因此也不再有 PS/2 接口和 PS/2 协议存在。

KSC 和 KBC 的功能全部集成在一个专用 MCU 中,即集成在 EC 中。

EC 作为一个专用 MCU,设计有 8*18 的键盘扫描模块,实现矩阵键盘的扫描。EC 也设计有 LPC 总线,和 PCH 实现 IO 6064 通讯。因此在 EC 固件中即可实现 KBC 功能。

EC 这颗专用 MCU 集成了原先 KBC 的功能,因此 EC 也会叫 KBC。

如今笔记本电脑中,EC 键盘系统设计框图如下:

mcu

06—Keyboard Init

EC 键盘的实际工作原理和 PS/2 键盘基本一致,其中的 KBC 需要被 Host 端 Driver 初始化后,才能正常工作。

KBC 由 EC 固件实现,因此上述 KBC、KSC 相关的指令必须由 EC 固件实现,并且返回正确的值,否则 OS 端 KB Driver 初始化无法完成,会导致Windows 系统下设备管理器中 PS/2 设备出现黄色感叹号,键盘无法使用。

UEFI 环境下,KBC 初始化。

EC 固件实现了 KBC 逻辑后,添加必要的 log后,当 UEFI 环境启动后会对 KBC 初始化。EC 端 log 如下图:

mcu

上图是在 EC 中记录了进入 UEFI Shell 环境时的键盘初始化序列。

通讯释义
1Host->EC, i8042 cmd[AD]8042 command Disable Keyboard
2Host->EC, i8042 cmd[A7]8042 command Disable Mouse
3Host->EC, i8042 cmd[AA]8042 command Self Test
4EC->Host, data=[55]EC Response test results
5Host->EC, i8042 cmd[60]8042 command Write controller config byte
6Host->EC, i8042 data[67]controller config byte is 0x67
7Host->EC, i8042 data[F4]Send to IO_60 without command
8Host->EC, i8048 cmd[F4]8048 command Enable matrix scan
9EC->Host, data=[FA]EC send “ACK”,must 0xFA
10Host->EC, i8042 cmd[AB]8042 command Keyboard interface test
11EC->Host, data=[00]EC Response test results,must 00
12Host->EC, i8042 data[FF]Send to IO_60 without command
13Host->EC, i8048 cmd[FF]8048 command Reset and start self-test
14EC->Host, data=[FA]EC send “ACK”,must 0xFA
15EC->Host, data=[AA]EC Response test results
17Host->EC, i8042 data[F0]Send to IO_60 without command
18Host->EC, i8048 cmd[F0]8048 command Get/set current scan code set
19EC->Host, data=[FA]EC send “ACK”,must 0xFA
20Host->EC, i8042 data[02]Send to IO_60 without command
21Host->EC, i8048 cmd[02]8048 sub-command select scancode set-2
22EC->Host, data=[FA]EC send “ACK”,must 0xFA
23Host->EC, i8042 data[F4]Send to IO_60 without command
24Host->EC, i8048 cmd[F4]8048 command Enable matrix scan
25EC->Host, data=[FA]EC send “ACK”,must 0xFA
26Host->EC, i8042 data[ED]Send to IO_60 without command
27Host->EC, i8048 cmd[ED]8048 command control LED status
28EC->Host, data=[FA]EC send “ACK”,must 0xFA
29Host->EC, i8042 data[00]Send to IO_60 without command
30Host->EC, i8048 cmd[00]8048 set LED off
31EC->Host, data=[FA]EC send “ACK”,must 0xFA

上述初始化过程在如下文件中可以找到:

UDK2018/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c

mcu

OS 环境下,KBC 初始化。

Windows 或者 Linux 系统在加载过程中,BIOS 声明了 PS/2 键盘设备后,OS 内置的 PS/2 Keyboard Driver 就会加载,完成 EC 内 KBC 和 KSC 的初始化,以及配置。当然 Windows Inbox PS/2 Driver 看不到源码,感兴趣的话可以看看 Linux PS/2 Driver 的源码。

需要注意的是,UEFI 和 OS 下 KBC 初始化流程基本一致。

差异点是,UEFI 环境下 CPU 不响应 SERIRQ 中的 IRQ-1,靠轮询的方式工作。OS下 CPU 需要响应 IRQ-1,当有键盘中断触发后,Driver 才会被回调,处理 IO 60/64 的数据。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分