新聞中心

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

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

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

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

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]

此次筆記記錄完畢。



評論


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

關(guān)閉