所谓键位冲突和无冲突的各种原理
轉(zhuǎn)至:https://www.cnblogs.com/noble/p/4144213.html? ? 博客園
***************************************************分割線**************************************************
最近閑得無聊,正好看到有人發(fā)帖提問,于是就來詳細(xì)說說所謂鍵位沖突和無沖突的各種原理——基本上這也是個老生常談的話題了,但相關(guān)的技術(shù)帖比較零亂難找,而且充斥了大量電工術(shù)語,也不是很容易看懂。這里就盡量用通俗易懂的語言來講(我的目標(biāo)是即使你只有初中文化水平也能看懂,保守地說絕對不超過高中文科生能理解的范圍),帖子比較長,有興趣的朋友請慢慢閱讀。慢慢看,用心理解,包你看懂。
為了降低閱讀門檻,本文難免有不嚴(yán)謹(jǐn)之處,還請工科同學(xué)高抬貴手。如果是特別荒謬的原則性錯誤,歡迎指正。
——————電路基本常識:輸出與輸入——————
我們的手指按下一個鍵,電腦是怎么知道的呢?在這短短幾十微秒的時間里發(fā)生了什么事呢?為什么有時候同時按下幾個鍵就沒反應(yīng)了呢?首先要講講電路的通斷。
即使你沒有什么計算機知識,大概也應(yīng)該聽過一個詞:【二進(jìn)制】。不管你家里的電腦外表多么五顏六色,它底層的邏輯卻是非黑即白,只有【1】和【0】。任何儲存在你電腦里的東西,無論游戲、音樂還是你最鐘愛的小電影,都是用一長串你數(shù)不清的1和0的組合來記錄和處理的。
明白了這個概念以后,再想想,電腦電腦,它的基礎(chǔ)是什么?對,要有【電】。下一個問題很自然地:這電怎么就能變成1和0呢?說來更簡單,有電就是1,沒電就是0唄——這么說似乎太不專業(yè)了。嚴(yán)謹(jǐn)一點說:在電路中一個點,它當(dāng)前表示的數(shù)據(jù)是1還是0,需要檢測這一點的電壓到底是更接近【懸空】(對于USB和PS/2接口,指+5V),還是更接近【大地】(0V)。如果高于某個界限值,稱作【高電平】,也就是1;而相對地,低于某個界限值,稱作【低電平】,也就是0。
接下來的問題更是小學(xué)生也會答:1×1等于多少?
你當(dāng)然知道答案是1。
那么1×0呢?
對了,不管什么數(shù)字乘以0,結(jié)果都是0。
如同在游泳池里面尿尿一樣,一泡尿就把干凈水變成臟水。大地就是這么邪惡:無數(shù)個懸空的點,它們之間互相連接還是懸空,然而只要其中有一個點接著地,它們就全等于接地了。
(重要知識)高電平的點和低電平的點連通短接之后,兩點都成為低電平。
你壓住不耐煩,看到這里,心想,這他媽的和鍵盤有毛的關(guān)系?
別著急,我們再來看看一個典型的可編程芯片是什么樣子(圖片引自泡泡網(wǎng)的poker拆解):
?
這個黑色方方的就是芯片,它周圍那一排排張牙舞爪的刺叫做【引腳】,是芯片用來和外界溝通的渠道,圖中這只芯片一共有48個引腳。
其中一些引腳負(fù)責(zé)電源、時鐘、控制等基礎(chǔ)功能,但占絕對多數(shù)的是負(fù)責(zé)輸入/輸出數(shù)據(jù)的,稱為【I/O引腳】。
通過程序設(shè)置,芯片既可以改變每個I/O引腳的電壓(設(shè)置1或0的值),也可以檢測引腳的電壓(讀取1或0的值),以下如果沒有特殊說明,提到引腳一詞均指數(shù)據(jù)I/O引腳。
現(xiàn)在請假設(shè)這樣一個場景:
你是一顆芯片,你的左手和右手是兩個引腳,有一大團雜亂無章的導(dǎo)線,露出兩個線頭擺在你面前,你如何判斷它們是否是同一根線的兩頭?(即這兩個線頭是否連通)
仔細(xì)考慮之后,聰明的你大概可以想到:只要把左手設(shè)置為0,右手設(shè)置為1,分別握上兩個線頭,然后檢查右手的狀態(tài),如果變成0了,說明它們剛剛做過一次相乘運算,1被拉下水變成了0,這條線是連通的。
換一個比喻:如同一根管道,在左手的洞口放一只小老鼠,右手的洞口放一塊奶酪(這只小老鼠的速度無敵快)。當(dāng)小老鼠從左邊進(jìn)去,又從右邊鉆出來吃掉了奶酪,說明管道中間沒有被堵死。
對,這就是鍵盤按鍵接通的原理。
在按鍵下面的【電路板】(或者電路薄膜)上,印制有許多導(dǎo)線,導(dǎo)線經(jīng)過每個按鍵下方的部分是斷開的。按鍵,也就是開關(guān),當(dāng)它壓下的時候,下面的導(dǎo)線會被接通。而導(dǎo)線最終兩端都是連接到芯片上,芯片會不停地反復(fù)檢測每條線的連通情況,從而隨時判斷哪個鍵當(dāng)前是按下的。這就好像學(xué)校的保安頭子坐在監(jiān)控室里,切換著鏡頭,偷窺哪個自習(xí)室中有男女生OOXX那樣。
——————主控芯片與矩陣設(shè)計——————
我們繼續(xù)深入話題:一塊普通的鍵盤,少則幾十個多則上百個按鍵,顯然無論從哪個方面看,怎么都不可能給每個鍵都單獨連個導(dǎo)線到CPU芯片去——先不說成本多高,誰愿意桌面上橫著手腕粗的一大捆線呢?
在上個世紀(jì)末,電腦開始走入尋常百姓家庭,當(dāng)時的PC界霸主是IBM公司。為了簡化接口,順便壟斷標(biāo)準(zhǔn),IBM陸續(xù)設(shè)計了XT、AT、PS/2協(xié)議用來處理鍵盤這樣的輸入設(shè)備,大體意思是,只要在鍵盤內(nèi)部放一塊主控芯片,用來管理所有按鍵狀態(tài)并轉(zhuǎn)換為串行信號,包括電源在內(nèi)總共只要4根線就可以傳輸所有的數(shù)據(jù)(掃描碼),而相應(yīng)地,主板上也會有一個稱作鍵盤控制器的IO芯片(一般集成在南橋中),把這些掃描碼翻譯為ASCII碼給CPU。
最后,PS/2協(xié)議作為成熟而穩(wěn)定的形態(tài),成為了二十多年來的市場規(guī)范,也就是大家熟知的那個圓形接口,里面實際用到的4根線分別負(fù)責(zé):時鐘、數(shù)據(jù)、電源、接地。
上面這一段可能有點復(fù)雜,如果你沒能全看懂,也沒啥大礙,只是為了說明【鍵盤主控芯片】的存在。
總之,整理一下到目前為止的知識,現(xiàn)在你應(yīng)當(dāng)知道鍵盤是遵循如下的通訊過程:
【按鍵】——【鍵盤主控芯片】——(翻譯成掃描碼,經(jīng)過PS/2協(xié)議)——【主板IO芯片】——(翻譯成ASCII碼)——【CPU】
這樣看起來不錯,但還有個問題:主控芯片是怎么“知道”所有鍵的狀態(tài)的?
按照前面說的,要得知一個按鍵是否按下,需要在引腳A輸出0,引腳B輸出1,再檢測引腳B的值是1還是0。(如果這里看不懂就麻煩了,請向上翻翻,復(fù)習(xí)一下左右手攥電線或者小老鼠吃奶酪的例子)
現(xiàn)在,假設(shè)我們要做一個36鍵的鍵盤,包括10個數(shù)字和26個英文字母。
于是我們令引腳A永遠(yuǎn)=0,而且連接到所有的按鍵上。
然后做引腳B1、B2、B3、……、B36,分別與對應(yīng)的36個按鍵連接。
這樣總共是需要37個引腳。
接著,先令所有B引腳=1,然后從B1到B36挨個檢查,誰變成0了,就說明誰對應(yīng)的按鍵按下了。當(dāng)然,為了時刻獲取最新的狀態(tài),每秒鐘要進(jìn)行幾十至上百輪這樣的掃描。
但是104個鍵的鍵盤怎么辦?老老實實做105個引腳嗎?這也太復(fù)雜了吧!有沒有辦法能用更小、更簡單一些的芯片實現(xiàn)呢?要知道這可直接關(guān)系到成本啊。
工程師們想了個辦法:【矩陣】。聽起來很專業(yè),其實就是利用“組合”,來成倍地提高引腳利用率。還拿上面的例子說,我們可以把引腳數(shù)量從37縮減到12。怎么做呢?
請想象一個表格,行標(biāo)題為A1、A2、A3、A4、A5、A6,列標(biāo)題為B1、B2、B3、B4、B5、B6。這樣就構(gòu)成了一個6×6=36的矩陣。然后把按鍵分別放到每個格子里面去,如下圖。
?
在電路中,每個按鍵都是負(fù)責(zé)連接它所對應(yīng)的兩個引腳,比如按鍵A連接引腳A1和B1,而按鍵W連接A5和B4。這樣一來,引腳之間就形成了【交叉組合關(guān)系】,也就是矩陣。任意兩個引腳之間只通過一個按鍵連接。
現(xiàn)在我們按下J鍵,芯片中的程序是怎么檢測到這個行動的呢?
首先令A(yù)1=0,其他所有引腳=1,然后從B1到B6挨個檢查。由于那一列的按鍵都沒有按下,沒有任何一個B引腳和A1接通,因此它們的值都是1。
接下來,令A(yù)2=0,其他所有引腳=1,重復(fù)以上工作。接著再檢查A3列……
最后所有行列檢查完畢后,結(jié)果發(fā)現(xiàn)只有在A4=0的時候,B2=0,也就是說A4和B2是接通的。于是程序便通過預(yù)先定義好的按鍵表格,知道按下的是J鍵。
同樣地,這一整輪掃描每秒要重復(fù)幾十上百遍,所以你在任何時候敲下或抬起按鍵,電腦都能很快反應(yīng)出來。
現(xiàn)在市面上絕大多數(shù)鍵盤的工作原理都是基于這種矩陣的。我們很容易想到,矩陣的行數(shù)乘以列數(shù)的結(jié)果,就是它能夠容納按鍵的最大數(shù)量。普通的104鍵鍵盤是應(yīng)用16×8的矩陣,來覆蓋所有按鍵。只需要24個數(shù)據(jù)引腳。
?
——————三鍵沖突:矩陣的麻煩——————
如果你耐心地一行一行讀到這里,我相信經(jīng)過了兩節(jié)的鋪墊,你已經(jīng)掌握了足以繼續(xù)讀下去的基礎(chǔ)知識。那么廢話到此為止,下面開始介紹本帖的重點問題:【鍵位沖突】。
在剛才的段落中,你已經(jīng)知道了系統(tǒng)是如何判定單個鍵有沒有按下的。但我們?nèi)祟惖碾p手上長了十個手指,誰也不能保證不會同時按下兩個按鍵——甚至很多時候組合鍵是故意設(shè)計要用的。這樣一來,就會有一個潛在的問題出現(xiàn)……
請回憶一下剛才用來舉例的36格矩陣圖,如果我們同時按下B、H、G鍵,在程序看來是什么樣子呢?
像平時一樣,它從(A1,B1)開始檢測,現(xiàn)實中我們并沒有按下A鍵,所以當(dāng)A1=0,其他引腳=1的時候,B1的值應(yīng)該是1,表示A鍵沒有被按下才對。但是,請注意:
由于G鍵被按下,A1和B2是接通的,
由于H鍵被按下,B2和A2是接通的,
由于B鍵被按下,A2和B1也是接通的!
也就是說,現(xiàn)在的電路中,A1和B1其實是連在一起的!
還記得嗎?不管多少個1相乘,只要中間有0,最后就會變成0。
換句話說,我們見A1和B1沒有直接連通,就天真地以為B1的奶酪不會被吃掉——但有個致命的錯誤就在于我們根本不關(guān)注其它奶酪。瞬間,電流飛馳,經(jīng)過3個按鍵,最終鉆進(jìn)地下。這只飛快的小老鼠沿著管線從A1出發(fā),先是吃掉了B2的奶酪,然后又吃掉了A2,最后從B1鉆出來大快朵頤。(注:嚴(yán)格來說,其實老鼠與電流方向是相反的,此處的比喻是為了更容易理解)
就這樣,芯片以為A鍵也被按下了。
事實上,按下這4鍵中的任意3鍵,在電腦看來都是相同的,因為A1、A2、B1、B2這四點已經(jīng)變成短路的狀態(tài)。
任意兩行兩列所構(gòu)成的4個交點,也即某長方形的四角所對應(yīng)的4個鍵,同時按下3個時,都會出現(xiàn)這樣的問題——在四通八達(dá)的管道中,剩余的那個鍵的狀態(tài)到底是按下還是沒按下,對于芯片來講是一片茫然。怎么辦呢?
掃描按鍵的程序是人寫的,稍作改動也不是不可能。于是需要增加如下的處理方法:給它一個“小賬本”,隨時記錄當(dāng)前按下的所有按鍵。每當(dāng)按下或抬起某個鍵時,就在賬本中如實增加或抹除。但是,如果賬本顯示:某個“四角組合”其中已經(jīng)有兩個按鍵同時按下時,這個組合剩余的鍵就被邏輯鎖定——即使你按了,程序也拒絕接受,除非之前的某個鍵抬起。
這樣設(shè)計的理由很簡單:寧可錯殺一千,不能放過一個,不知道按沒按的話,當(dāng)成沒按更保險。你能想象當(dāng)你同時按下B鍵和G鍵以后,再按H鍵,屏幕上出現(xiàn)的卻是A嗎?太無厘頭了,還不如什么反應(yīng)都沒有。
這也就是所謂的三鍵沖突的原型所在。
任何沒做無沖處理的矩陣式鍵盤,都存在許多特定的三鍵組合不能同時按。舉個著名的例子,黑寡婦的A、W、L。
你可能會說:“不會啊我的鍵盤可以七鍵一起按都沒沖突的。”
是的,不同品牌型號的鍵盤走線設(shè)計可能有區(qū)別,因此它們存在沖突的鍵位也不一樣。只要不構(gòu)成四角組合關(guān)系,大部分鍵都是可以隨便同按的,以打字為主要用途的普通鍵盤,即使有這樣那樣的沖突,也足夠日常使用了。
但是四角組合數(shù)不勝數(shù)——比如上面例子中6×6的矩陣就存在多達(dá)55個四角組合,220種三鍵沖突,可想而知全尺寸鍵盤會有多少個鍵位沖突。雖然大部分沖突組合都是你平時不會按到的,但玩游戲的時候需要的鍵位總是千奇百怪各不相同,比如玩勁樂團可能需要SDF空格JKL不沖突,而BMIIDX則需要ZSXDCFV不沖突。如果你什么都玩,有很大幾率會碰到那么一兩個沖突鍵位郁悶?zāi)恪<词箤︽I盤最沒要求的FPS游戲,還是有少數(shù)鍵盤的四角組合悲劇地包含QWA或者1WD之類經(jīng)常需要一起按的鍵……
一個比較討巧的辦法就是把左側(cè)常用十來個鍵位的走線全部串到一起,這樣至少可以保證打CS情緒穩(wěn)定。因為我們知道,會起沖突的按鍵是位于任意兩行兩列的4個交點中的3個,而全部處于同一列或同一行的鍵,不管怎么按也不會沖突。
當(dāng)然,最完美的還是全鍵盤無沖突,也就是所謂的【NKRO】。這就要放在下一節(jié)講了。
——————無沖突的技術(shù)本源——————
之前你已經(jīng)意識到了,普通的矩陣鍵盤,都會存在成百上千的三鍵沖突組合。但是市面上卻有那么幾款鍵盤,號稱全鍵無沖突,實際測試也是威武異常,整個手掌拍下去都能毫不猶豫地識別出來,這是為什么呢?
這里要介紹一個美妙的電氣元件——【二極管】。
二極管是計算機邏輯電路最基本的元件之一(包括CPU芯片在內(nèi)的各種集成電路芯片內(nèi)部都有大量的二極管和三極管),大家津津樂道的LED就是二極管中能發(fā)光的一種。
一個典型的二極管會有兩條腿,即陽極和陰極。它的特點就是——電流只能從它的陽極流向陰極,而反向則難以通過。
如果身為芯片的你捏著一個二極管的兩端,你左手是1,右手是0時,只消一瞬間,左手的1就會變成0。但若調(diào)換成右手是1,左手是0,右手的1則不會受到影響。這二極管就相當(dāng)于一個單向的小門,老鼠只可以從這邊跑到那邊,卻不能從那邊跑到這邊。
那么這個特點對我們具體有什么幫助呢?
只要你回憶一下按鍵沖突的問題是如何產(chǎn)生的,就會恍然大悟了。
沖突,是為了防止當(dāng)A1和B2、A2和B2、A2和B1分別連通時,程序誤以為A1和B1也連通,因此當(dāng)發(fā)現(xiàn)3個按鍵互相形成回路時,就屏蔽第三顆按鍵的設(shè)計。
現(xiàn)在,我們在每個按鍵的電路中增加一個二極管,讓小老鼠只能從A端跑到B端,而不能從B跑向A。
回到之前的例子,同時按下B、H、G三個鍵。盡管H鍵接通了A2和B2,但由于二極管的限制,信息只能從A2到B2傳導(dǎo),而不能從B2到A2。
于是,雖然受G鍵按下的影響,當(dāng)A1=0的時候,B2的值被修改為0,但這個0在這里就到此為止了。因為老鼠到達(dá)B2后,被門擋住,無法繼續(xù)去吃A2的奶酪。既然A2不會跟著變成0,而是保持正確的1,B1的值當(dāng)然也還是1。
由此,系統(tǒng)自然能夠判斷出,A鍵沒有被按下,和事實一致。也就是說,二極管的防逆流特性,徹底消除了按鍵之間的干擾。
有了這些二極管做保障,自然根本不需要什么屏蔽第三顆按鍵的邏輯了。于是,每一顆按鍵可以獨立自主反應(yīng),活動自如,成就了我們的無沖突鍵盤。
至于為什么無沖突鍵盤基本都是機械鍵盤,我想可能有兩個原因:
1,機械鍵盤采取的電路板比較容易安裝二極管。而薄膜鍵盤基本無解。
2,機械鍵盤本身的定位也比較高,相對這個售價水平來講,增加一百顆二極管的成本并不顯著。
——————USB永遠(yuǎn)的痛——————
講了這么多,終于到最后一節(jié)了。前面已經(jīng)把造成鍵盤沖突的原理和解決辦法從頭到尾介紹了一遍,但還沒有講過USB接口的鍵盤,即使硬件上是NKRO結(jié)構(gòu)了,為什么還是只能做到6鍵無沖突。
這里所指的6鍵,是除去Ctrl、Shift、Alt、Win之外的鍵,同時按下任意6個都不會有沖突,但第7個鍵按下就沒有反應(yīng)——或者會直接抹掉第一個鍵,總之邏輯上同時只能有6個鍵處于按下的狀態(tài)。
但是這樣的鍵盤,使用PS2轉(zhuǎn)接頭連接電腦,又可以實現(xiàn)完美NKRO(除了部分鍵盤干脆不支持PS/2轉(zhuǎn)接,例如poker)。
看來問題就出在USB接口上了。
事實上的確是這樣,因為鍵盤輸入設(shè)備在USB接口和PS/2接口的傳輸協(xié)議完全不同,也就是說,它們采取了完全不同的工作方式,也難怪效果不同。現(xiàn)在你能買到的大部分機械鍵盤,其主控芯片可以根據(jù)當(dāng)前連接的端口,自動適應(yīng)PS/2或USB協(xié)議。只有少量無法轉(zhuǎn)接。
既然你已經(jīng)堅持看到這里了,我相信你對它們的具體區(qū)別會比較感興趣,別著急,這就慢慢道來。
(還是有些廢話:如果你搞不清【字節(jié)】和【位】的概念請看本段)
位(bit,縮寫為小寫的b),就是二進(jìn)制位,取值范圍只有0和1兩個值,是最小的單位。
字節(jié)(Byte,縮寫為大寫的B),為8個位的組合,取值范圍是從0到255(2的8次方),也是常見的計算機數(shù)據(jù)量單位。
1字節(jié)=8位,所以如果你的網(wǎng)速標(biāo)稱10Mb,實際下載速度只有1.25MB。
PS/2協(xié)議下,鍵盤是每次發(fā)生按鍵/抬鍵動作,都會發(fā)送數(shù)據(jù)信號給主機。通常按下一個鍵這個動作所包含的數(shù)據(jù)(通碼)為1或2個字節(jié),抬起一個鍵(斷碼)則是2或3個字節(jié)。如果按住一個鍵不放,則會不停地向主機循環(huán)發(fā)送通碼,直到抬起按鍵發(fā)送斷碼。根據(jù)10-20kHz的工作頻率規(guī)范,每位數(shù)據(jù)的傳輸時間大約是40-80微秒,加上中間的保留延遲,每個字節(jié)會占用0.5-1ms的傳輸時間。不過在實際應(yīng)用中,這個延遲完全可以接受——即使像鐵拳那樣以幀來計算的格斗游戲,對出招的嚴(yán)格度也不會低于16ms。
而USB協(xié)議下,鍵盤會以某個固定的回報率(每秒125-1000次),定期向主機發(fā)送當(dāng)前按鍵的狀態(tài),每次發(fā)送8個字節(jié),這8個字節(jié)的具體內(nèi)容則是:
第一個字節(jié):8位分別表示左右的Ctrl、Shift、Alt、Win各自是否被按下。這8個鍵統(tǒng)稱為【modifer key】,因為規(guī)范已經(jīng)事先定義好每一位的含義,從而得以能夠只用一個字節(jié)就表示8個鍵的狀態(tài)。
第二個字節(jié):保留(無用)
其余6個字節(jié):當(dāng)前正按下的6個【普通按鍵】(如果按了7個以上,根據(jù)鍵盤主控芯片內(nèi)置的程序,可能取最先按的6個,也可能取最后按的6個)。
即每1-8ms,可以發(fā)送最多14個按鍵的狀態(tài)信息。
發(fā)現(xiàn)問題所在了吧?如果說按鍵是上廁所的人,傳輸協(xié)議是看守廁所的大叔……
PS/2大叔會一直盯著廁所門口,每次有人進(jìn)去就向主機匯報,有人出來再匯報。
USB大叔呢,則是急急忙忙沖進(jìn)廁所,看有哪些人在,記在小紙條上,然后跑出來一起匯報,之后再沖進(jìn)去,如此循環(huán)。可惜他的小紙條地方太小,只夠?qū)懴?個人的名字(另外還有8位鬧肚子的熟客是事先打好招呼的,只要用暗號記載匯報就可以)。
所以說,USB協(xié)議下,包含兩邊的Ctrl、Shift、Alt、Win在內(nèi),單鍵盤最多只能同時識別14個鍵。如果只算普通鍵,則只能同時識別6個。
至于最近一年剛興起的【USB無沖】技術(shù),似乎是通過將一個物理鍵盤虛擬成多個邏輯鍵盤實現(xiàn)的,程序兼容性還有待提高,在此暫且不表。
關(guān)于鍵盤沖突那點事,差不多也說完了。感謝你耐心閱讀本文
總結(jié)
以上是生活随笔為你收集整理的所谓键位冲突和无冲突的各种原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: uniapp的项目,scss和js实现跑
- 下一篇: 使用docker创建属于你的ChatGP