按鍵是一種常開型按鈕開關(guān),與單片機(jī)的常見接法如圖所示。按鍵未按下時(shí)兩個(gè)觸點(diǎn)斷開,單片機(jī)I/O口輸入高電平;當(dāng)按鍵閉合時(shí),I/O口輸入低電平。
一、按鍵講解
當(dāng)I/O口為P0口時(shí),由于沒有內(nèi)部上拉電阻,所以必須外接上拉電阻,當(dāng)I/O口為P1、P2和P3口時(shí),由于內(nèi)部已有上拉電阻,因此可省略外接的上拉電阻。
二、按鍵消抖
單片機(jī)系統(tǒng)中所使用的鍵盤都是機(jī)械式的彈性按鍵,因?yàn)榇嬖跈C(jī)械觸點(diǎn)的彈性作用,在按鍵閉合和彈起的瞬間都會(huì)出現(xiàn)抖動(dòng),如圖所示。按鍵抖動(dòng)一般會(huì)持續(xù)5~10ms,為使一次按鍵僅被處理一次,必須消除按鍵抖動(dòng)。消除按鍵抖動(dòng)可以采用軟件消抖或硬件消抖。
軟件消抖指在檢測(cè)到有按鍵閉合時(shí),延時(shí)一小段時(shí)間之后再次檢測(cè),如果仍然檢測(cè)到按鍵閉合,則認(rèn)為按鍵真正閉合。
硬件消抖方法
1.R-S觸發(fā)器
一旦有鍵按下,觸發(fā)器立即反轉(zhuǎn),觸點(diǎn)的抖動(dòng)便不會(huì)再對(duì)輸出產(chǎn)生影響,按鍵釋放時(shí)也一樣。
2.電容濾波
將電容并聯(lián)在按鍵的兩端,利用電容放電的延時(shí)特性,將產(chǎn)生抖動(dòng)的電平通過電容吸收掉,從而達(dá)到消抖的作用;
三、獨(dú)立按鍵
獨(dú)立鍵盤指每個(gè)按鍵都占據(jù)一個(gè)獨(dú)立的引腳。
四、矩陣按鍵
同一行上的所有按鍵都連接到一個(gè)引腳,同一列上的所有按鍵都連接到一個(gè)引腳。
(1)列掃描方式
所有行線都輸出高電平,列線依次輸出低電平;查詢?cè)摿猩闲械闹?,若?,則說明該行上的按鍵被按下;若該列上所有行的值都為1,則進(jìn)行下一列行值的查詢;循環(huán)往復(fù)。
(2)反轉(zhuǎn)法
所有行線都輸出0,查詢列線上的值,若某列線上的值為0,則說明該列線上的按鍵被按下;然后所有列線都輸出0,查詢行線上的值,若某行線上的值為0,則說明該行線上的按鍵被按下;從而確定某行某列的按鍵被按下。
五、程序舉例
#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char
uint key,key_num;//鍵盤掃描值,鍵盤鍵值
/********************************************************************/
//函數(shù)名:delay_1ms(uint x)
//功能:利用定時(shí)器0精確定時(shí)1ms;自加 time_t的值為后面時(shí)間調(diào)整函數(shù)服務(wù)
//調(diào)用函數(shù):
//輸入參數(shù):x,1ms計(jì)數(shù)
//輸出參數(shù):
//說明:延時(shí)的時(shí)間為1ms乘以x
/********************************************************************/
void delay_1ms(uint x)
{
TMOD=0X01;//開定時(shí)器0,工作方式為1
TR0=1;//啟動(dòng)定時(shí)器0;
while(x--)
{
TH0=0Xfc;//定時(shí)1ms初值的高8位裝入TH0
TL0=0X18;//定時(shí)1ms初值的低8位裝入TL0
while(!TF0);//等待,直到TF0為1
TF0=0;
}
TR0=0;//停止定時(shí)器0;
}
/**********************************************************/
//函數(shù)名:keyscan()
//功能:得出4x4鍵盤的行列掃描值
//調(diào)用函數(shù):delay_1ms(uint x)
//輸入?yún)?shù):
//輸出參數(shù):
//說明:通過P1口的掃描得出掃描值key,無(wú)鍵按下key為16
/**********************************************************/
uchar keyscan()
{
uchar code_h; //行掃描值
uchar code_l; //列掃描值
P1=0XF0; //P1.0-P1.3全為0,(行狀態(tài)全為低電平)
if((P1&0xF0)!=0XF0) //如果P1.4-P1.7不全為1,可能有鍵按下(為準(zhǔn)確識(shí)別按鍵動(dòng)作)
{
delay_1ms(5); //廷時(shí)去抖動(dòng),為準(zhǔn)確識(shí)別按鍵動(dòng)作
if((P1&0xF0)!=0XF0)//重讀高4位(列狀態(tài)),若還是不全為1,定有鍵按下
{
code_h=0xfe; //開始行掃描 (0xfe:11111110)
while((code_h&0x10)!=0x00)//判斷是否掃描四行(X0~X3)完畢,若不是,繼續(xù)掃描(0x10:00010000)
{
P1=code_h; //第1次P1.0置為0,其余高電平;第2次P1.1置為0,其余高電平 ;第3次P1.2置為0,其余高電平;第4次P1.3置為0,其余高電平
if((P1&0xF0)!=0XF0) //如果P1.4-P1.7不全為1,該行有鍵按下(0xF0:11110000)
{
code_l=(P1&0xF0|0x0F);//保留P1口高4位,低4位變?yōu)?,作為列值
return((~code_h)+(~code_l));//鍵盤編碼=行掃描值+列掃描值 (取反后用,相當(dāng)于改為按下按鍵對(duì)應(yīng)的行、列標(biāo)識(shí)為1,其它為0)
}
else //左移后補(bǔ)0,但是我們需要將其他位置1,所以+1
code_h=(code_h<<1)|0x01; //若該行無(wú)鍵按下,行掃描值左移+1,掃描下一行
}
}
}
return(16); //無(wú)鍵按下,返回16
}
/**********************************************************/
//函數(shù)名:keynum()
//功能:得出4x4按鍵的鍵值
//調(diào)用函數(shù):keyscan()
//輸入?yún)?shù):
//輸出參數(shù):
//說明:通過key的值確定按鍵鍵值
/**********************************************************/
void keynum()
{
uchar i,j;
uchar code tab[4][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11},{12,13,14,15}};
//4x4鍵盤各鍵值標(biāo)注
key=16;
key = keyscan();//引入key值
if((key&0x01)!=0) i=0; //判斷出按下按鍵的行列號(hào) (即找出低電平的行、列)
if((key&0x02)!=0) i=1;
if((key&0x04)!=0) i=2;
if((key&0x08)!=0) i=3;
if((key&0x10)!=0) j=0;
if((key&0x20)!=0) j=1;
if((key&0x40)!=0) j=2;
if((key&0x80)!=0) j=3;
if(key!=16)
{
key_num = tab[i][j];//通過比較得出4x4鍵盤的鍵值
}
}
void main()
{
uint shi,ge;
shi = 0;
ge = 0;
P2 = 0x16;//初始值 為16
while(1)
{
keynum(); //獲取到鍵值
if(key!=16)
{
shi = key_num/10;//獲得十位
ge = key_num%10;//獲得個(gè)位
if(shi)
{
P2 = 0x10|ge;
}
else
{
P2 = ge;
}
}
delay_1ms(10);//延時(shí)
}
}
-
按鍵
+關(guān)注
關(guān)注
4文章
223瀏覽量
57602 -
按鈕開關(guān)
+關(guān)注
關(guān)注
1文章
50瀏覽量
10219 -
i/o
+關(guān)注
關(guān)注
0文章
33瀏覽量
4593
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論