咱們每敲擊一次電腦鍵盤,按鍵對應的字符就會出如今顯示器上。這中間發生了什麼?請聽我慢慢細說。算法
人對按鍵的操做,從兩個維度去描述,一個是「動做」,另外一個是「內容」。數組
按下一個按鍵,鬆開一個按鍵,按下一個按鍵而且保持按住狀態一段時間(長按),這些都是動做。編碼
每一個按鍵和動做組合起來,會傳送給計算機一個編碼,這就是內容,術語是「掃描碼」,對應的英語詞彙是scan code
。操作系統
按下按鍵、長按鍵對應的掃描碼叫「Make Code」,鬆開按鍵對應的掃描碼叫「Break Code」。設計
Break Code
和Make Code
的關係是:Break Code = Make Code & 0x80
。code
爲何兩種編碼之間有上面的關係?設計人員特地這樣設計的。硬件
在鍵盤上執行某種操做(按鍵、長按、鬆開鍵)時,8048會檢測到這個操做,把這個操做對應的掃描碼發送給8042。數據
到如今爲止,出現了三套編碼方案,咱們如今的鍵盤通常使用第2套方案。計算機
8042從8048接收到第2套方案的掃描碼後,把它轉換成第1套掃描碼,而且放入緩衝區,最後,通知8259A發生了鍵盤中斷。語言
中斷例程取走緩衝區的數據後,8042纔會接收新的數據。緩衝區的數據不被取走,8042就不會接收新數據。
8259A接收來自8042的鍵盤中斷,讓操做系統分派中斷例程處理緩衝區的數據。
在第1套掃描碼中,一個Make Code對應一個按鍵。咱們能夠經過Make Code識別出當前被按下的鍵是哪一個鍵。例如,A
鍵的Make Code是0x1E
;當操做系統接收到的Make Code是0x1E
時,就能夠認爲接收到的數據是A
。
然而,問題出現了。咱們在實際輸入中有輸入A
和a
的需求。可掃描碼方案中只有A
的掃描碼,沒有a
的掃描碼。相似的按鍵還有數字鍵一、二、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行)。
shift
鍵)。shift
鍵)。然而,在鍵盤上存在不可打印的字符,例如esc、F一、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
鍵只有Make Code,沒有Break Code。這是僅有的特例,其餘鍵同時具備Make Code和Break Code。
Pause
鍵的Make Code是E一、1D、4五、E一、9D、C5
。識別一個鍵是否是Pause
的算法是:
檢查Make Code的開頭是否是`E1。
Pause
鍵。1D、4五、E一、9D、C5
。不是,不是Pause
鍵;是,是Pause
鍵。識別算法和Pause
鍵相同。
下回分解。