4x4鍵盤(pán)編程心得
在單片機(jī)系統(tǒng)中,只要單片機(jī)有空余的時(shí)間來(lái)解碼時(shí),我們往往利用的是軟件解碼的形式,即“非編碼鍵盤(pán)”來(lái)實(shí)現(xiàn)矩陣鍵盤(pán)。這樣可以節(jié)約成本。下面我就對(duì)矩陣鍵盤(pán)在51單片機(jī)中的軟件解碼方式應(yīng)用總結(jié)一下。
本文引用地址:http://m.butianyuan.cn/article/201611/317337.htm原理圖:
工作原理:
掃描程序查詢的內(nèi)容如下:
&129;查詢是否有鍵按下。首先單片機(jī)向行掃描口P1.0~P1.3輸出全為0的掃描碼F0H,然后從列檢測(cè)口P1.4~P1.7輸入列檢測(cè)信號(hào),只要有一列信號(hào)不為1,即P1口不為F0H,則表示有鍵按下。接著要查出按下鍵所在的行、列位置。
&8218;查詢按下鍵所在的行、列位置。單片機(jī)將得到的信號(hào)取反,P1.4~P1.7口中為1的位置便是鍵所在位置。
接下來(lái)要確定鍵所在的行,需進(jìn)行行逐行掃描。單片機(jī)首先使用P1.0口接地,P1.1~P1.7口為1,即向P1口發(fā)送掃描碼FEH,接著輸入列檢測(cè)信號(hào),若為全1,則表示不在第一行。然后使P1.1接地,其余為1,再讀入列信號(hào)……。這樣逐行發(fā)0掃描碼,直到找到按鍵所在的行,將該行掃描碼取反保留。若各行都掃描以后仍沒(méi)有找到,則放棄掃描,認(rèn)為是鍵的誤動(dòng)作。
&402;對(duì)得到的行號(hào)和列號(hào)譯碼,得到鍵值。
&8222;鍵的消抖處理。當(dāng)用手按下一個(gè)鍵時(shí),往往會(huì)出現(xiàn)所按鍵在閉合位置和斷開(kāi)位置之間跳幾下才穩(wěn)定到閉合狀態(tài)的情況;在釋放一個(gè)鍵時(shí),也會(huì)出現(xiàn)類(lèi)似的情況。這就是鍵抖動(dòng)。抖動(dòng)的持續(xù)時(shí)間不一,通常不會(huì)大于10ms。若抖動(dòng)問(wèn)題不解決,就會(huì)引起對(duì)閉合鍵的多次讀入。解決鍵抖動(dòng)最方便的方法是:當(dāng)發(fā)現(xiàn)有鍵按下后,不要立即進(jìn)行逐行掃描,而是延時(shí)10ms后再進(jìn)行。由于鍵按下的時(shí)間會(huì)持續(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);//無(wú)鍵按下,返回值為0
}
說(shuō)明:
此按鍵掃描函數(shù)是很多書(shū)上介紹的按鍵掃描函數(shù),從原來(lái)的角度來(lái)說(shuō)是完全正確可行的。但是在我上次做《密碼鎖》時(shí),發(fā)現(xiàn)用此函數(shù)比較麻煩,且總是存在一些問(wèn)題。通過(guò)查閱大量書(shū)籍和實(shí)驗(yàn),我寫(xiě)出了比較簡(jiǎn)單而且切實(shí)可行的按鍵掃描程序。
程序如下:
/*****************************************************
函數(shù)名:ucharKey_scan(void)
功能:4x4按鍵,按鍵掃描
說(shuō)明:對(duì)按鍵進(jìn)行掃描,從而得到鍵編碼
入口參數(shù):無(wú)
返回值:有鍵按下返回:鍵編碼=行掃描值+列掃描值;無(wú)按鍵返回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);//無(wú)鍵按下,返回0
}
/*****************************************************
函數(shù)名:ucharKey_switch(void)
功能:按鍵轉(zhuǎn)換程序
說(shuō)明:對(duì)按鍵碼進(jìn)行轉(zhuǎn)換
入口參數(shù):無(wú)
返回值: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;/*"無(wú)"鍵*/
}
}
/*接盤(pán)按鍵說(shuō)明:
--------------------------------------------------
|1|2|3|A|
-------------
|4|5|6|B|
-------------
|7|8|9|C|
-------------
|*|0|#|D|
--------------------------------------------------
說(shuō)明:
如果需要更改按鍵值,只需改Key_switch()函數(shù)中對(duì)應(yīng)的返回值即可。對(duì)于延時(shí)函數(shù)比較簡(jiǎn)單只需一個(gè)for循環(huán)即可,所以在這里就沒(méi)寫(xiě)出來(lái)。因每個(gè)單片機(jī)的I/O的應(yīng)用是不一樣的,所以本人寫(xiě)的這個(gè)函數(shù)只能在51單片機(jī)系統(tǒng)下運(yùn)行。如果要在別的單片機(jī)系統(tǒng)下,可能需要用第一種進(jìn)行改進(jìn)。
評(píng)論