咱们每敲击一次电脑键盘,按键对应的字符就会呈现在显示器上。这两头产生了什么?请听我缓缓细说。
相干概念
人对按键的操作,从两个维度去形容,一个是“动作”,另一个是“内容”。
按下一个按键,松开一个按键,按下一个按键并且放弃按住状态一段时间(长按),这些都是动作。
每个按键和动作组合起来,会传送给计算机一个编码,这就是内容,术语是“扫描码”,对应的英语词汇是scan code
。
按下按键、长按键对应的扫描码叫“Make Code”,松开按键对应的扫描码叫“Break Code”。
Break Code
和Make Code
的关系是:Break Code = Make Code & 0x80
。
为什么两种编码之间有下面的关系?设计人员特意这样设计的。
三个硬件
8048
在键盘上执行某种操作(按键、长按、松开键)时,8048会检测到这个操作,把这个操作对应的扫描码发送给8042。
到当初为止,呈现了三套编码方案,咱们当初的键盘个别应用第2套计划。
8042
8042从8048接管到第2套计划的扫描码后,把它转换成第1套扫描码,并且放入缓冲区,最初,告诉8259A产生了键盘中断。
中断例程取走缓冲区的数据后,8042才会接管新的数据。缓冲区的数据不被取走,8042就不会接管新数据。
8259A
8259A接管来自8042的键盘中断,让操作系统分派中断例程解决缓冲区的数据。
流程
- 人类敲击键盘,8048监测到”敲击了哪个键“,把对应的扫描码传送给8042。
- 8042接管到8048的数据后,将数据转换成第1套扫描码,放入缓冲区;而后告诉8259A。
- 8259A接管到告诉后,通知操作系统产生了键盘中断。
- 操作系统运行键盘中断例程把缓冲区的数据取走;8042又能够从新接管新数据了。
解析扫描码
映射数组
在第1套扫描码中,一个Make Code对应一个按键。咱们能够通过Make Code辨认出以后被按下的键是哪个键。例如,A
键的Make Code是0x1E
;当操作系统接管到的Make Code是0x1E
时,就能够认为接管到的数据是A
。
然而,问题呈现了。咱们在理论输出中有输出A
和a
的需要。可扫描码计划中只有A
的扫描码,没有a
的扫描码。相似的按键还有数字键1、2、3
等。怎么解决这个问题呢?
先看看上面这个表格。
Make Code
0
1
2
0x1E
a
A
0
0x02
1
!
0
在下面的表格中,Make Code是行号,每行有三个不同的值。0x1E
行的第0列表示意a
,0x1E
行的第1列示意A
。
这可能实现一个键示意两种不同的值。
咱们平时怎么取得一个键的不同值呢?以数字键1
为例。敲击数字键1
时,获取的值是1
;同时按下shift
键和数字键1
时,获取的值是感叹号!
。
在具体实现中,依据是否同时按下了shift
键来决定是获取第X行的第0列还是第1列。显然,按下shift
键,获取第1列;没有按下shift
键,获取第0列。
第1套扫描码一共有0x80
个,其实就是ASCII
码表中元素的个数。
咱们仿照下面的表格建设一个元素更多的表格TB(表头雷同,行数裁减到0x80行)。
- 第一列是行号,值是Make Code,假如是A。
- 第二列是A对应的键的默认值(没有按下
shift
键)。 - 第二列是A对应的键的另一个值(按下了
shift
键)。
然而,在键盘上存在不可打印的字符,例如esc、F1、F2
等。在TB中,这些不可打印的键对应的值是咱们设置的某个数值(这一行的第0列和第1列的数值雷同)。
怎么应用TB?依据Make Code找到对应的行,依据是否按下了shift
键决定是获取第0列还是第1列的值。
要在C语言中应用这个表格,只能将它用数组示意进去。把这个表格的每一行的第0列、第1列、第2列
按程序组成一个数组keyMap
。
如果接管到的Make Code是MC,没有按下shift
键,对应的值是keyMap[MC * 3]
;按下shift
键,对应的值是keyMap[MC * 3 + 1]
。
反正就是这么回事,硬是要解释一下怎么弄出这个数组的,我解释不分明。
Pause
Pause
键只有Make Code,没有Break Code。这是仅有的特例,其余键同时具备Make Code和Break Code。
Pause
键的Make Code是E1、1D、45、E1、9D、C5
。辨认一个键是不是Pause
的算法是:
查看Make Code的结尾是不是`E1。
- 不是,不是
Pause
键。 - 是,持续查看残余的扫描码是不是
1D、45、E1、9D、C5
。不是,不是Pause
键;是,是Pause
键。
- 不是,不是
Print Screen
辨认算法和Pause
键雷同。
其余
下回分解。