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