51 線(xiàn)反轉法 實(shí)現矩陣鍵盤(pán)檢測
1.矩陣鍵盤(pán) 線(xiàn)反轉法算法
1.1矩陣鍵盤(pán)
矩陣鍵盤(pán)是指將鍵盤(pán)按鈕放置在行線(xiàn)與列線(xiàn)的交叉點(diǎn)上,由多行和多列就構成了矩陣鍵盤(pán)。下圖就是一個(gè)矩陣式鍵盤(pán)。
將鍵盤(pán)行線(xiàn)接到單片機的引腳之上[P35引腳,P36引腳],將鍵盤(pán)列線(xiàn)接到單片機的另一些引腳之上[P31引腳,P32引腳,P33引腳,P34引腳]。
1.2線(xiàn)反轉法算法
對于外部鍵盤(pán),程序在執行時(shí)必須隨時(shí)掃描鍵盤(pán)跟單片機連接引腳的電平,看是否有鍵盤(pán)按鈕被按下。而在掃描各個(gè)端口的時(shí)候,一次只能掃描到按鍵的哪一行或那一列,只有同時(shí)記錄被按下按鍵的行和列才能決定按鍵的坐標。
最直接的方式是先逐行檢測有哪一行的按鍵被按下,再逐列檢測有哪一列的按鈕被按下。這樣就能夠得到按鍵的行值和列值即得到按鍵的坐標,就檢測到了是哪一個(gè)按鍵被按下了。但是使用這種方法程序執行效率就跟矩陣的行數R和列數C有關(guān)了,每次檢測都需要檢測R * R次。
到了21世紀,線(xiàn)反轉法肯定會(huì )替代以上掃描方法的,因為這種檢測方法只需要兩次就可以?huà)呙璩鰜?lái)是哪一個(gè)按鍵被按下了。它是如何來(lái)實(shí)現就用掃面兩次就可以得到按鍵的坐標的呢?單片機的引腳在默認情況下為高電平,將接接矩陣鍵盤(pán)行的引腳置位低電平(0)[如上圖P3就應該被置為],將接矩陣鍵盤(pán)列的引腳置位高電平(1),則結合上圖中的2X4鍵盤(pán)的P3端口的值應為宏值#define ROW_LOW_COLUMN_HIGH 0x9f,然后檢測接矩陣鍵盤(pán)列中是否有低電平出現,如果有則說(shuō)明在低電平列有按鈕被按下;若檢測到某列為低電平后,確定是哪一列,然后將行和列所接引腳電位反轉:行為高電平,列為低電平(結合上圖P3端口為宏值#define ROW_HIGH_COLUMN_LOW 0xe1),檢測行是否有高電平的行,如果有則確定是哪一行為高電平即確定哪一行有按鍵被按下。這樣就確定了一個(gè)按鍵的行和列坐標。
1.3線(xiàn)反轉法代碼實(shí)現
將以下函數放置在main函數中的主程序循環(huán)中就可以檢測到是否有按鍵被按下并得知按鍵的行坐標和列坐標:實(shí)現代碼如下
KEY_INDEX matrixKeyDown(){UINT temp;KEY_INDEX key_index;//鍵盤(pán)行為低電平,列為高電平P3 = ROW_LOW_COLUMN_HIGH;temp = P3;temp = temp & KEY_ALL_UP_IN_COLUMN;//檢測按鍵有沒(méi)有被按下if(temp != KEY_ALL_UP_IN_COLUMN){//消除是按鍵抖動(dòng)引起的嫌疑nms_delay(10);//再次檢測鍵盤(pán)有沒(méi)有被按下temp = P3;temp = temp & KEY_ALL_UP_IN_COLUMN;//檢測按鍵被按下的列if(temp != KEY_ALL_UP_IN_COLUMN){temp = P3;switch(temp){case KEY_DOWN_IN_FIRST_COLUMN:key_index.column = FIRST_COLUMN_INDEX;break;case KEY_DOWN_IN_SECOND_COLUMN:key_index.column = SECOND_COLUMN_INDEX;break;case KEY_DOWN_IN_THIRD_COLUMN:key_index.column = THIRD_COLUMN_INDEX;break;case KEY_DOWN_IN_FOURTH_COLUMN:key_index.column = FOURTH_COLUMN_INDEX;break;default:; //Do something}}//矩陣鍵盤(pán)端口反轉,檢測按鍵所在的行//此時(shí)的按鍵還在被按住,但是還是判斷一下按鍵是否還被按住//與檢測列的按下并列,需要檢測P3 = ROW_HIGH_COLUMN_LOW;temp = P3;temp &= KEY_ALL_UP_IN_ROW;if(temp != KEY_ALL_UP_IN_ROW){temp = P3;switch(temp){case KEY_DOWN_IN_FIRST_ROW:key_index.row = FIRST_ROW_INDEX;break;case KEY_DOWN_IN_SECOND_ROW:key_index.row = SECOND_ROW_INDEX;break;default:;}//如果有按鍵被按下,則需要在這里等待被釋放//思路是記錄到底是哪一個(gè)鍵被按下,可以換一個(gè)地方等待案件的釋放的//因為其它地方記錄了按鍵的坐標//其實(shí)只需要在這里檢測若行為KEY_ALL_UP_IN_ROW,則按鍵被釋放//temp = P3;//while(temp != KEY_ALL_UP_IN_ROW);}}return key_index; }
此函數時(shí)檢測矩陣鍵盤(pán)中是否有按鍵被按下。KEY_INDEX是一個(gè)包含按鍵行和列坐標的結構體。temp = temp &KEY_ALL_UP_IN_COLUMN; KEY_ALL_UP_IN_COLUMN宏值為0x9f表示在列中的鍵盤(pán)全為高電平時(shí)的狀態(tài),if(temp != KEY_ALL_UP_IN_COLUMN)表示若temp與此值做與運算后的值不為鍵盤(pán)全列為高電平狀態(tài),則可能(還有可能是抖動(dòng)帶來(lái)的干擾)有按鍵被按下,于是用自定義延遲函數nms_delay(10);延遲10ms的時(shí)間來(lái)消除鍵盤(pán)抖動(dòng)(目的是進(jìn)一步判斷是否是按鍵真的被按下),然后用相同的方法判斷一次鍵盤(pán)是否全列都為高電平狀態(tài),如果不是,則此時(shí)確實(shí)有按鍵被按下,則接下來(lái)用case語(yǔ)言判斷是哪一列的按鍵被按下,將被按下按鍵的列賦值給結構體的列值,從而得到按鍵的列值。得到列值之后,將接矩陣鍵盤(pán)行和列引腳P3反轉,因為此時(shí)已經(jīng)有按鍵被按下,所以無(wú)需再做消擾動(dòng)等操作。只需檢測是哪一行的按鍵被按下得到被按下按鍵的行值即可,代碼中還判斷了是否行值被按下,其實(shí)此時(shí)已經(jīng)有按鍵被按下,這一步可有可無(wú)。
最后函數將按鍵的列值和行值返回,供數碼管或LCD中顯示,是哪一個(gè)按鍵被按下了。實(shí)現人機合作。
2 擴展
這里代碼是對2X4矩陣鍵盤(pán)的掃描,其實(shí)以上程序設計方法適合任何矩陣鍵盤(pán)和任何其它的芯片。需要變動(dòng)的是接矩陣鍵盤(pán)的端口:將接矩陣鍵盤(pán)行引腳和列引腳找出來(lái)賦予合適的宏值[高低電平,將進(jìn)行檢測的行或列置成高電平,另一些引腳置為低電平]。另外還需要改動(dòng)的一個(gè)地方是,判斷矩陣式哪一行和哪一列被按下,增加一些行和列值即可。
3 運行結果
將鍵盤(pán)檢測函數的返回值送給數碼管動(dòng)態(tài)顯示(數碼管動(dòng)態(tài)顯示)函數,再將數碼管動(dòng)態(tài)顯示函數放置在主程序循環(huán)中。下載程序到單片機中,運行程序,當按下第一行第二列的按鍵時(shí),數碼管顯示如下
按鍵[1][3]
按下2,4按鍵時(shí)顯示結果如下
按鍵[2][4]
此次筆記記錄完畢。
評論