新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 51 線反轉(zhuǎn)法 實現(xiàn)矩陣鍵盤檢測

51 線反轉(zhuǎn)法 實現(xiàn)矩陣鍵盤檢測

作者: 時間:2016-11-20 來源:網(wǎng)絡(luò) 收藏
背景:STC89C52RC單片機

本文引用地址:http://butianyuan.cn/article/201611/318607.htm

1.矩陣鍵盤 線反轉(zhuǎn)法算法

1.1矩陣鍵盤

矩陣鍵盤是指將鍵盤按鈕放置在行線與列線的交叉點上,由多行和多列就構(gòu)成了矩陣鍵盤。下圖就是一個矩陣式鍵盤。

將鍵盤行線接到單片機的引腳之上[P35引腳,P36引腳],將鍵盤列線接到單片機的另一些引腳之上[P31引腳,P32引腳,P33引腳,P34引腳]。

1.2線反轉(zhuǎn)法算法

對于外部鍵盤,程序在執(zhí)行時必須隨時掃描鍵盤跟單片機連接引腳的電平,看是否有鍵盤按鈕被按下。而在掃描各個端口的時候,一次只能掃描到按鍵的哪一行或那一列,只有同時記錄被按下按鍵的行和列才能決定按鍵的坐標。

最直接的方式是先逐行檢測有哪一行的按鍵被按下,再逐列檢測有哪一列的按鈕被按下。這樣就能夠得到按鍵的行值和列值即得到按鍵的坐標,就檢測到了是哪一個按鍵被按下了。但是使用這種方法程序執(zhí)行效率就跟矩陣的行數(shù)R和列數(shù)C有關(guān)了,每次檢測都需要檢測R * R次。

到了21世紀,線反轉(zhuǎn)法肯定會替代以上掃描方法的,因為這種檢測方法只需要兩次就可以掃描出來是哪一個按鍵被按下了。它是如何來實現(xià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),檢測行是否有高電平的行,如果有則確定是哪一行為高電平即確定哪一行有按鍵被按下。這樣就確定了一個按鍵的行和列坐標。

1.3線反轉(zhuǎn)法代碼實現(xiàn)

將以下函數(shù)放置在main函數(shù)中的主程序循環(huán)中就可以檢測到是否有按鍵被按下并得知按鍵的行坐標和列坐標:實現(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:;}//如果有按鍵被按下,則需要在這里等待被釋放//思路是記錄到底是哪一個鍵被按下,可以換一個地方等待案件的釋放的//因為其它地方記錄了按鍵的坐標//其實只需要在這里檢測若行為KEY_ALL_UP_IN_ROW,則按鍵被釋放//temp = P3;//while(temp != KEY_ALL_UP_IN_ROW);}}return 	key_index;	}


此函數(shù)時檢測矩陣鍵盤中是否有按鍵被按下。KEY_INDEX是一個包含按鍵行和列坐標的結(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與此值做與運算后的值不為鍵盤全列為高電平狀態(tài),則可能(還有可能是抖動帶來的干擾)有按鍵被按下,于是用自定義延遲函數(shù)nms_delay(10);延遲10ms的時間來消除鍵盤抖動(目的是進一步判斷是否是按鍵真的被按下),然后用相同的方法判斷一次鍵盤是否全列都為高電平狀態(tài),如果不是,則此時確實有按鍵被按下,則接下來用case語言判斷是哪一列的按鍵被按下,將被按下按鍵的列賦值給結(jié)構(gòu)體的列值,從而得到按鍵的列值。得到列值之后,將接矩陣鍵盤行和列引腳P3反轉(zhuǎn),因為此時已經(jīng)有按鍵被按下,所以無需再做消擾動等操作。只需檢測是哪一行的按鍵被按下得到被按下按鍵的行值即可,代碼中還判斷了是否行值被按下,其實此時已經(jīng)有按鍵被按下,這一步可有可無。

最后函數(shù)將按鍵的列值和行值返回,供數(shù)碼管或LCD中顯示,是哪一個按鍵被按下了。實現(xiàn)人機合作。

2 擴展

這里代碼是對2X4矩陣鍵盤的掃描,其實以上程序設(shè)計方法適合任何矩陣鍵盤和任何其它的芯片。需要變動的是接矩陣鍵盤的端口:將接矩陣鍵盤行引腳和列引腳找出來賦予合適的宏值[高低電平,將進行檢測的行或列置成高電平,另一些引腳置為低電平]。另外還需要改動的一個地方是,判斷矩陣式哪一行和哪一列被按下,增加一些行和列值即可。

3 運行結(jié)果

將鍵盤檢測函數(shù)的返回值送給數(shù)碼管動態(tài)顯示(數(shù)碼管動態(tài)顯示)函數(shù),再將數(shù)碼管動態(tài)顯示函數(shù)放置在主程序循環(huán)中。下載程序到單片機中,運行程序,當按下第一行第二列的按鍵時,數(shù)碼管顯示如下

按鍵[1][3]

按下2,4按鍵時顯示結(jié)果如下

按鍵[2][4]

此次筆記記錄完畢。



評論


技術(shù)專區(qū)

關(guān)閉