傳統(tǒng)的各類電子專業(yè)的教科書上以及可查閱的文獻(xiàn)資料中,有關(guān)MCU做鍵盤矩陣的掃描解讀,大都是通過逐行逐列掃描、鍵值計(jì)算、鍵對(duì)應(yīng)特征量返回、查表等數(shù)據(jù)處理的方式來進(jìn)行掃描解讀的。為此還得設(shè)定在求鍵值時(shí)以輔助保存原值的行值、列值緩沖寄存器等,有的為了保證鍵每閉合一次MCU只作一次處理,往往會(huì)在程序運(yùn)行中等閉合鍵釋放后才對(duì)其進(jìn)行鍵解釋處理。這樣鍵盤的掃描解讀頗占CPU時(shí)間,降低了CPU的工作效率。本文揭示的是一種基于布爾處理的新穎的鍵盤矩陣解讀方法。下面結(jié)合圖示并以6×5鍵盤矩陣解讀為例進(jìn)行描述。 1 程序結(jié)構(gòu) 基于布爾處理的鍵盤矩陣解讀方法,也就是使整個(gè)鍵盤矩陣的掃描解讀過程都能歸結(jié)為系列的布爾“位”的操作。掃描解讀過程主要包括如下步驟:定義各標(biāo)志位;鍵盤矩陣輸出線掃描;查詢有無鍵按下;查詢鍵解讀標(biāo)志位;消抖動(dòng)延時(shí);查詢相對(duì)應(yīng)的哪個(gè)輸示端口電平有變化;查詢相對(duì)應(yīng)的哪個(gè)輸出端口輸出掃描電平;相對(duì)應(yīng)的哪個(gè)鍵作具體的解釋處理;置位鍵解讀標(biāo)志位,流程如圖1所示。 2 步驟闡述 2.1 定義各標(biāo)志位 充分利用現(xiàn)行MCU內(nèi)部能進(jìn)行位操作的RAM資源,運(yùn)用偽指令來定義系統(tǒng)中所牽涉的各標(biāo)志位。由于偽指令所揭示的定義只寫在源程序的頭文件上,是不會(huì)產(chǎn)生可執(zhí)行目標(biāo)代碼的,因而對(duì)標(biāo)志位定義的“操作”在圖1的程序流程簡(jiǎn)圖中就沒有表述。 圖1 鍵盤矩陣掃描程序流程簡(jiǎn)圖 2.2 鍵盤矩陣輸出線掃描 輸出線掃描過程也是通過逐個(gè)改變輸出行線端口的電平來實(shí)現(xiàn)的,如圖2所示。輸入口線平常所有端口都處于高電平狀態(tài);輸出口線是逐個(gè)循環(huán)的輸出低電平,也就是任何時(shí)候只有一個(gè)口線輸出低電平;通過鍵的按下接通,才有可能拉低相對(duì)應(yīng)輸入口線的端口電平。 圖2 鍵盤矩陣電路結(jié)構(gòu) 如果系統(tǒng)中配置有數(shù)碼顯示電路,則電路結(jié)構(gòu)如圖3所示。輸入口線平常也都處于高電平狀態(tài);輸出口線卻是逐個(gè)循環(huán)的輸出高電平,通過反相組件后掃描線才成為低電平;通過鍵的按下接通,同樣拉低相對(duì)應(yīng)輸入口線的端口電平。這樣將鍵盤輸出線掃描能與數(shù)碼顯示的位掃描程序合二為一了,也就能省卻了鍵盤掃描的單獨(dú)執(zhí)行,把鍵盤掃描納入到系統(tǒng)掃描顯示的大循環(huán)中。 圖3 帶數(shù)碼位矩陣電路結(jié)構(gòu) 2.3 查詢有無鍵按下 有無鍵按下自然是通過對(duì)鍵盤掃描輸入口狀況的查詢來確定的。有鍵按下,鍵盤掃描輸入端口也就相應(yīng)有所改變了。 如果輸入端口如圖2所示,是集中在同一個(gè)Pn口的(其中,n=0,1,2,…),那么可以用對(duì)整個(gè)Pn口的字節(jié)數(shù)據(jù)的判別來確定鍵有否按動(dòng);也可運(yùn)用依次對(duì)Pn口的幾個(gè)端口Pn.y進(jìn)行位的查詢來確定有無鍵按下,其中,y=0、1、2、3、4。 如果輸入口不是集中的,為了設(shè)計(jì)布線的方便而零亂分散于P0口、P2口……Pn口等不同的P口上,那么只能通過依次地對(duì)輸入各端口的位狀態(tài)變化的查詢來確定有否鍵按下。若檢查到有鍵按下,就轉(zhuǎn)入到鍵盤矩陣掃描解讀程序;若沒有鍵按下,則清一次鍵解讀標(biāo)志位為邏輯0,為下次按鍵解讀作好準(zhǔn)備。 2.4 查詢鍵解讀標(biāo)志位 檢查有鍵按下后首先查詢鍵解讀標(biāo)志位的狀態(tài)是處于邏輯0還是邏輯1;若是邏輯0說明本次按鍵尚未解讀過,經(jīng)消抖動(dòng)延時(shí)后需進(jìn)一步對(duì)鍵盤矩陣的輸出、輸入口線進(jìn)行查詢來確定是哪一個(gè)鍵,并作相應(yīng)處理。 若鍵解讀標(biāo)志位是邏輯1,則表明本次按鍵已解讀過了,沒必要浪費(fèi)CPU時(shí)間,可直接從鍵掃描處理程序中返回。這就實(shí)現(xiàn)了鍵每閉合一次,MCU只作一次處理的效果。改變了傳統(tǒng)的為了保證鍵每閉合一次,MCU只作一次處理,程序中需等待鍵釋放后才對(duì)其進(jìn)行解釋的弊病。 2.5 消抖動(dòng)延時(shí) 當(dāng)覺察有鍵按下、查詢鍵解讀標(biāo)志位為0時(shí),就置位消抖動(dòng)延時(shí)標(biāo)志位及其輔助位進(jìn)入消抖動(dòng)延時(shí)處理。消抖動(dòng)延時(shí)的具體進(jìn)行可調(diào)備用的消抖動(dòng)延時(shí)程序;也可借助對(duì)系統(tǒng)大循環(huán)次數(shù)的計(jì)數(shù)或動(dòng)用MCU內(nèi)部定時(shí)器的中斷來實(shí)現(xiàn)消抖動(dòng)延時(shí),這樣就不必設(shè)置專門的延時(shí)程序而占用CPU的時(shí)間了。消抖動(dòng)延時(shí)結(jié)束時(shí)清零消抖動(dòng)延時(shí)標(biāo)志位及其輔助位。 2.6 查詢哪個(gè)輸入口線電平有變化 平常所有輸入端口都處于高電平,經(jīng)消抖動(dòng)延時(shí)后就查詢鍵盤矩陣各輸入口線的電平是否有被拉低。若一個(gè)端口也沒被拉低,則說明本次按鍵無效(可能是某種干擾引起的“抖動(dòng)”),于是直接返回。 若依次查詢作為輸入的Pn.y各端口的其中某個(gè)端口電平被拉低,則表明本次按鍵是有效的,將跳轉(zhuǎn)至查詢與該口線交叉相關(guān)的那個(gè)輸出口線。 2.7 掃描哪個(gè)輸出口線輸出有效電平 圖2所示的鍵盤矩陣電路結(jié)構(gòu)中,輸出端口Pm.x與輸入端口Pn.y是直接由鍵連接交叉的。當(dāng)鍵按下時(shí)哪一個(gè)輸入端口的電平被拉低確定后,則跳轉(zhuǎn)到查詢Pm.x(Pm.0、Pm.1、Pm.2、Pm.3、Pm.4、Pm.5)六個(gè)端口中是哪個(gè)端口輸出低電平,進(jìn)而確定具體哪一個(gè)鍵按下,跳轉(zhuǎn)至幾號(hào)鍵進(jìn)行解釋處理。任何時(shí)候掃描輸出低電平的端口是唯一的,也只有行掃描輸出低電平的那個(gè)Pm.x口,才會(huì)將列輸入Pn.y口的電平拉低。這時(shí),鍵按下有效交叉的行、列相應(yīng)端口都處于低電平。 若運(yùn)用典型的51系列MCU的指令去寫匯編程序來解讀矩陣的具體鍵時(shí),則有: Key_scan:JNB Pn.y,Key_matrix_j ;當(dāng)輸入端口Pn.y(y=0,1,2,3,4)被拉低時(shí),跳轉(zhuǎn)至Key_matrix_j(j=y) LJMPReturn ;若端口Pn.y一個(gè)也沒被拉低,則返回 Key_matrix_j: JNBPm.x,Key_gloze_i ;當(dāng)知曉Pn.y的某個(gè)端口被拉低,則再查詢Pm.x(x=0,1,2,3,4,5)的哪個(gè)端口掃描輸出低電平來確定具體是i號(hào)按鍵,則跳轉(zhuǎn)至Key_gloze_i(i=1,2,3,…,29,30)以對(duì)i號(hào)鍵作相應(yīng)的解釋處理 LJMPReturn Key_gloze_1:…;1號(hào)鍵解釋處理 LJMPReturn Key_gloze_2:…;2號(hào)鍵解釋處理 LJMPReturn … Key_gloze_29:…;29號(hào)鍵解釋處理 LJMPReturn Key_gloze_30:…;30號(hào)鍵解釋處理 Return:RET;鍵盤矩陣掃描解讀返回 圖4 鍵盤矩陣掃描倒樹形結(jié)構(gòu) 以上匯編語言所述的鍵盤矩陣掃描解讀過程,可借助圖4來較形象化地解釋。由圖4可見,每一Pn.y(y=0,1,2,3,4)口都與Pm.x(x=0,1,2,3,4,5)的6個(gè)口有關(guān)聯(lián),而每一Pn.y口線與Pm.x的6個(gè)口線中任一口線相交都揭出一個(gè)鍵(i號(hào)),結(jié)合以上程序,若輸入端口Pn.0被拉低,且是端口Pm.1有效掃描輸出低電平,則有(JNBPn.0,Key_matrix_0)指令跳轉(zhuǎn)至Key_matrix_0,繼而查詢輸出端口(JNBPm.1,Key_gloze_6)跳轉(zhuǎn)至Key_gloze_6,也就是先查詢到Pn.0被拉低跳轉(zhuǎn)至Key_matrix_0→再查詢到Pm.1掃描輸出低電平跳轉(zhuǎn)至Key_gloze_6→揭出是6號(hào)鍵按下并賦予其相應(yīng)的解釋處理。以此類推。 如果鍵盤矩陣的電路結(jié)構(gòu)如圖3所示,其掃描輸出端口Pm.x不是直接與輸入端口Pn.y交叉的,而是經(jīng)過用于數(shù)碼顯示位驅(qū)動(dòng)的反相組件后再與入端口Pn.y交叉的。為此,其掃描輸出有效端口不是低電平了,而是輸出高電平經(jīng)反相組件后再成為低電平,通過按鍵同樣將與之交叉的輸入端口線拉低。所以,在查詢輸入端口時(shí)與圖2所示的是相同的,而在查詢掃描輸出有效端口時(shí)與圖2的就有所不同了。 圖2所示電路結(jié)構(gòu)查詢的是哪個(gè)端口掃描輸出低電平,有: JNBPm.x,Key_gloze_i; 圖3所示電路結(jié)構(gòu)查詢的卻是哪個(gè)端口掃描輸出高電平,則: JBPm.x,Key_gloze_i; 由圖4可知,若輸入端口Pn.2被拉低,且是端口Pm.3有效掃描輸出高電平,則有先查詢到Pn.2被拉低→再查詢到Pm.3掃描輸出高電平→揭出是18號(hào)鍵按下并賦予其相應(yīng)的解釋處理。依此類推。具體的程序跳轉(zhuǎn)如圖5所示,可見其過程都是位的查詢跳轉(zhuǎn)。 圖5 鍵盤矩陣掃描程序跳轉(zhuǎn)結(jié)構(gòu)圖 2.8 執(zhí)行各對(duì)應(yīng)鍵具體處理 因?yàn)檩敵隹诰為行線,與輸入口線為列線的交叉點(diǎn)是唯一的,故確定了輸出哪一端口與輸入哪一端口,也就確定了具體哪一個(gè)鍵(i號(hào)鍵)按下了,就能賦予該鍵相應(yīng)的解釋處理。整個(gè)過程中,沒必要區(qū)別哪個(gè)是數(shù)字鍵、哪個(gè)是功能鍵。每一個(gè)鍵的解讀都是等價(jià)的,是數(shù)字鍵就直接賦予其相應(yīng)的數(shù)值處理,是功能鍵就直接賦予其具體的功能解釋。 2.9 置位鍵解讀標(biāo)志位 為保證鍵每閉合一次MCU只作一次處理,每一次鍵解讀后都將置鍵解讀標(biāo)志位為邏輯1。對(duì)于鍵解讀標(biāo)志位的置位,可以在每一個(gè)鍵解釋處理完畢后進(jìn)行,也可在消抖動(dòng)延時(shí)后就進(jìn)行一次總置。不管鍵有多少個(gè),鍵解讀標(biāo)志位用的卻是同一個(gè)。 其實(shí),引入了鍵解讀標(biāo)志位,不只是控制鍵每閉合一次MCU只作一次處理,還可對(duì)那些持久按著的鍵有控地進(jìn)行多次處理(如用于對(duì)一些數(shù)據(jù)遞進(jìn)、或遞減的連續(xù)設(shè)置等)。 3 原理綜述 本文提出基于布爾處理的鍵盤矩陣解讀方法。其原理如下: 在鍵盤矩陣掃描時(shí),首先檢查有否鍵按動(dòng)。若無鍵按動(dòng),則清零一次鍵解讀標(biāo)志位就返回;若有鍵按下,則再查詢鍵解讀標(biāo)志位是邏輯0還是邏輯1。如果是邏輯1,表明本次按鍵已解讀過,可直接從鍵掃描處理程序中返回;如果是邏輯0,說明本次按鍵尚未解讀過,則啟用消抖動(dòng)延時(shí)。經(jīng)消抖動(dòng)延時(shí)后即查詢鍵盤矩陣輸入口線的各端口是否有拉低。若一個(gè)端口也沒被拉低,則說明本次按鍵無效,那可能是某種干擾引起的“抖動(dòng)”,立即從鍵掃描處理程序中返回;若查詢到其中之一端口的電平被拉低了,則表明本次按鍵盤是有效的,將跳轉(zhuǎn)查詢與之相交的那個(gè)掃描有效輸出口線,進(jìn)而確定具體是哪一個(gè)鍵按下,并跳轉(zhuǎn)賦予其相應(yīng)的解釋處理。解釋處理后,置鍵解讀標(biāo)志位為邏輯1再返回,即完成一次鍵盤矩陣的掃描解讀。 不管鍵盤矩陣有多少個(gè)鍵,其掃描確定一個(gè)具體鍵所需位查詢的總次數(shù)S不會(huì)大于行數(shù)x與列數(shù)y之和;但也不少于2次,即2≤S≤x+y。如上述的6×5矩陣,最多所需位查詢總次數(shù)S=5+6=11。當(dāng)?shù)?0號(hào)鍵按下,查詢到最后一列Pn.4端口電平被拉低,繼而跳轉(zhuǎn)查詢到有效掃描輸出是最后一行Pm.5端口;但至少所需位查詢總次數(shù)S=1+1=2。當(dāng)1號(hào)鍵按下,先查詢到第1列Pn.0端口電平被拉低,繼而跳轉(zhuǎn)查詢到有效掃描輸出是第1行Pm.0端口。 結(jié)語 運(yùn)用布爾位操作處理進(jìn)行鍵盤矩陣的解讀,可適用于所有基于MCU的智能化儀器儀表中鍵盤矩陣的解讀。運(yùn)用布爾位操作方式,改變了傳統(tǒng)的用數(shù)據(jù)字節(jié)處理方式。掃描解讀過程中,沒有鍵值計(jì)算,沒有鍵對(duì)應(yīng)的特征值返回,同時(shí)也省去了求鍵值時(shí)以輔助保存原值的行值、列值緩沖寄存器等,有的只是位的操作查詢。構(gòu)成鍵盤矩陣的輸入口線可以是連續(xù)的,也可以是不連續(xù)的。在電路設(shè)計(jì)布線時(shí),哪一個(gè)端口方便就用哪個(gè)端口作鍵盤矩陣輸入線。換言之,輸入口線可隨意分散在不同P口中,這種靈活、便捷的方式是傳統(tǒng)的用鍵值處理的方式所不及的;同時(shí)也改變了傳統(tǒng)的為了保證鍵每閉合一次MCU只作一次處理,需等待鍵釋放后才對(duì)其進(jìn)行鍵解釋處理的做法。整個(gè)鍵盤矩陣的掃描顯得簡(jiǎn)捷、高效,鍵盤矩陣的解讀更為明快、準(zhǔn)確。 |