新聞中心

4x4鍵盤編程心得

作者: 時(shí)間:2016-11-10 來源:網(wǎng)絡(luò) 收藏
鍵盤在單片機(jī)系統(tǒng)中用得非常廣泛。當(dāng)按鍵多而且單片機(jī)的I/O口有限時(shí),往往要考慮的是矩陣式鍵盤。其中有兩種方式可以實(shí)現(xiàn)矩陣式鍵盤:一種是利用純硬件完成解碼的稱為“編碼鍵盤”;另外一種是利用軟件實(shí)現(xiàn)解碼的稱為“非編碼鍵盤”。

  在單片機(jī)系統(tǒng)中,只要單片機(jī)有空余的時(shí)間來解碼時(shí),我們往往利用的是軟件解碼的形式,即“非編碼鍵盤”來實(shí)現(xiàn)矩陣鍵盤。這樣可以節(jié)約成本。下面我就對矩陣鍵盤在51單片機(jī)中的軟件解碼方式應(yīng)用總結(jié)一下。

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

  原理圖:

工作原理:

掃描程序查詢的內(nèi)容如下:

&129;查詢是否有鍵按下。首先單片機(jī)向行掃描口P1.0~P1.3輸出全為0的掃描碼F0H,然后從列檢測口P1.4~P1.7輸入列檢測信號,只要有一列信號不為1,即P1口不為F0H,則表示有鍵按下。接著要查出按下鍵所在的行、列位置。

&8218;查詢按下鍵所在的行、列位置。單片機(jī)將得到的信號取反,P1.4~P1.7口中為1的位置便是鍵所在位置。

接下來要確定鍵所在的行,需進(jìn)行行逐行掃描。單片機(jī)首先使用P1.0口接地,P1.1~P1.7口為1,即向P1口發(fā)送掃描碼FEH,接著輸入列檢測信號,若為全1,則表示不在第一行。然后使P1.1接地,其余為1,再讀入列信號……。這樣逐行發(fā)0掃描碼,直到找到按鍵所在的行,將該行掃描碼取反保留。若各行都掃描以后仍沒有找到,則放棄掃描,認(rèn)為是鍵的誤動作。

&402;對得到的行號和列號譯碼,得到鍵值。

&8222;鍵的消抖處理。當(dāng)用手按下一個(gè)鍵時(shí),往往會出現(xiàn)所按鍵在閉合位置和斷開位置之間跳幾下才穩(wěn)定到閉合狀態(tài)的情況;在釋放一個(gè)鍵時(shí),也會出現(xiàn)類似的情況。這就是鍵抖動。抖動的持續(xù)時(shí)間不一,通常不會大于10ms。若抖動問題不解決,就會引起對閉合鍵的多次讀入。解決鍵抖動最方便的方法是:當(dāng)發(fā)現(xiàn)有鍵按下后,不要立即進(jìn)行逐行掃描,而是延時(shí)10ms后再進(jìn)行。由于鍵按下的時(shí)間會持續(xù)上百ms,延時(shí)后再掃描也不遲。

程序如下:

unsignedcharkey_scan(void)//按鍵掃描函數(shù)

{

unsignedcharsccode,recode;

P1=0xf0;//發(fā)全0行掃描碼,列線輸入

if((P1&0xf0)!=0xf0)//若有鍵按下

{

delay_ms(10);//延時(shí)去抖

if((P1&0xf0)!=0xf0)

{

sccode=0xfe;//逐行掃描初值

While((sccode&0x10)!=0)

{

P1=sccode;//輸出行掃描碼

if((P1&0xf0)!=0xf0)//本行有鍵按下

{

recode=(P1&0xf0)|0xf0;

return((~sccode)+(~recode));//返回特征字節(jié)碼

}

else

sccode=(sccode<<1)|0x01;//行掃描碼左移一位

}

}

}

return(0);//無鍵按下,返回值為0

}

說明:

此按鍵掃描函數(shù)是很多書上介紹的按鍵掃描函數(shù),從原來的角度來說是完全正確可行的。但是在我上次做《密碼鎖》時(shí),發(fā)現(xiàn)用此函數(shù)比較麻煩,且總是存在一些問題。通過查閱大量書籍和實(shí)驗(yàn),我寫出了比較簡單而且切實(shí)可行的按鍵掃描程序。

程序如下:

/*****************************************************

函數(shù)名:ucharKey_scan(void)

功能:4x4按鍵,按鍵掃描

說明:對按鍵進(jìn)行掃描,從而得到鍵編碼

入口參數(shù):無

返回值:有鍵按下返回:鍵編碼=行掃描值+列掃描值;無按鍵返回0

*****************************************************/

ucharKey_scan(void)

{

ucharkey;//存放鍵編碼

P1=0xf0;//發(fā)全0行掃描碼,列線輸入

if((P1&0xf0)!=0xf0)//若有鍵按下

{

delay_ms(10);//延時(shí)去抖

P1=0xf0;//取高4位值.即:列掃描值

key=P1&0xf0;//存放鍵編碼的高4位

P1=0x0f;//取低4位值.即:行掃描值

key=(P1&0x0f)|key;//低4位與高4位進(jìn)行合并

if(key!=0xff)

{

return(key);//有鍵按下,返回鍵編碼

}

}

return(0);//無鍵按下,返回0

}

/*****************************************************

函數(shù)名:ucharKey_switch(void)

功能:按鍵轉(zhuǎn)換程序

說明:對按鍵碼進(jìn)行轉(zhuǎn)換

入口參數(shù):無

返回值:ASCII碼

*****************************************************/

ucharKey_switch(void)

{

ucharkey;

key=Key_scan();

switch(key)

{

case0xee:return(49);break;/*"1"鍵*/

case0xed:return(50);break;/*"2"鍵*/

case0xeb:return(51);break;/*"3"鍵*/

case0xe7:return(65);break;/*"A"鍵*/

case0xde:return(52);break;/*"4"鍵*/

case0xdd:return(53);break;/*"5"鍵*/

case0xdb:return(54);break;/*"6"鍵*/

case0xd7:return(66);break;/*"B"鍵*/

case0xbe:return(55);break;/*"7"鍵*/

case0xbd:return(56);break;/*"8"鍵*/

case0xbb:return(57);break;/*"9"鍵*/

case0xb7:return(67);break;/*"C"鍵*/

case0x7e:return(42);break;/*"*"鍵*/

case0x7d:return(48);break;/*"0"鍵*/

case0x7b:return(35);break;/*"#"鍵*/

case0x77:return(68);break;/*"D"鍵*/

case0x00:return(00);break;/*"無"鍵*/

}

}

/*接盤按鍵說明:

--------------------------------------------------

|1|2|3|A|

-------------

|4|5|6|B|

-------------

|7|8|9|C|

-------------

|*|0|#|D|

--------------------------------------------------

說明:

如果需要更改按鍵值,只需改Key_switch()函數(shù)中對應(yīng)的返回值即可。對于延時(shí)函數(shù)比較簡單只需一個(gè)for循環(huán)即可,所以在這里就沒寫出來。因每個(gè)單片機(jī)的I/O的應(yīng)用是不一樣的,所以本人寫的這個(gè)函數(shù)只能在51單片機(jī)系統(tǒng)下運(yùn)行。如果要在別的單片機(jī)系統(tǒng)下,可能需要用第一種進(jìn)行改進(jìn)。



關(guān)鍵詞: 4x4鍵盤編程心

評論


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

關(guān)閉