吳允強(qiáng)++吳由松
摘 要 本文介紹了一種基于狀態(tài)機(jī)的單片機(jī)按鍵的實(shí)現(xiàn),通過(guò)狀態(tài)機(jī)實(shí)現(xiàn)按鍵的短按與長(zhǎng)按的功能,同時(shí)改進(jìn)按鍵消抖的方法,使單片機(jī)在節(jié)約CPU的資源的同時(shí)實(shí)現(xiàn)按鍵的各種狀態(tài)的檢測(cè),提高單片機(jī)的工作效率,整個(gè)設(shè)計(jì)代碼簡(jiǎn)潔,方便維護(hù)。
【關(guān)鍵詞】狀態(tài)機(jī) 按鍵 長(zhǎng)按
1 引言
在自己在科研實(shí)踐和對(duì)學(xué)生教學(xué)中發(fā)現(xiàn),現(xiàn)在單片機(jī)學(xué)習(xí)中對(duì)于按鍵處理的方法都是:檢測(cè)按鍵、延時(shí)消抖、按鍵執(zhí)行、等待釋放,整個(gè)按鍵處理的程序中大量出現(xiàn)“delay_1ms(5);”和“while(!key);”這樣的語(yǔ)句,這明顯是在給自己找麻煩,延時(shí)消抖與等待釋放需要消耗CPU運(yùn)行時(shí)間,執(zhí)行效率低下,而且這種方法處理的按鍵程序也實(shí)現(xiàn)不了按鍵的短按、長(zhǎng)按等靈活的按鍵操作方式。本文講述了一種用狀態(tài)機(jī)實(shí)現(xiàn)按鍵掃描的方法,達(dá)到按鍵的短按和長(zhǎng)按功能,高效的處理按鍵消抖問(wèn)題。
2 狀態(tài)機(jī)
狀態(tài)機(jī)在軟件編程中非常重要,一個(gè)思路清晰而且高效的程序,必然有狀態(tài)機(jī)的身影浮現(xiàn)。比如在按鍵命令解析程序中,本來(lái)是在狀態(tài)1中,觸發(fā)一個(gè)按鍵后切換到狀態(tài)2,再觸發(fā)另一個(gè)按鍵切換到狀態(tài)3,或者返回到狀態(tài)1。按鍵的擊鍵過(guò)程也是一種狀態(tài)的切換,也可以看著是一個(gè)狀態(tài)機(jī),一個(gè)按鍵的擊鍵過(guò)程包括:按下、抖動(dòng)、閉合、抖動(dòng)和釋放等狀態(tài)。我們只要把這些狀態(tài)機(jī)的思想想辦法用程序表示出來(lái)就可以了。
3 按鍵的狀態(tài)機(jī)實(shí)現(xiàn)
我們這里用狀態(tài)機(jī)是為解決問(wèn)題的,那么我們就要從問(wèn)題本身去思考。為了實(shí)現(xiàn)按鍵掃描,達(dá)到按鍵短按和長(zhǎng)按的功能,可以根據(jù)一個(gè)按鍵從按下按鍵到釋放按鍵的整個(gè)過(guò)程將按鍵分為4個(gè)狀態(tài):
S0:等待按鍵按下
S1:按鍵按下
S2:等待按鍵短按釋放
S3:等待按鍵長(zhǎng)按釋放
假設(shè)按鍵按下為低電平“0”,按鍵未按下為高電平“1”,按鍵的整個(gè)過(guò)程我們就可以通過(guò)狀態(tài)轉(zhuǎn)移圖表示出來(lái),如圖1所示。
首先,按鍵的初始狀態(tài)為S0,當(dāng)檢測(cè)到輸入為1時(shí),表示按鍵沒(méi)有按下,保持S0;當(dāng)輸入為0時(shí),表示按鍵按下,狀態(tài)轉(zhuǎn)入S1。在S1狀態(tài)中,檢測(cè)輸入信號(hào)是否為0,如果為0,執(zhí)行按鍵程序轉(zhuǎn)入S2;如果為1,表示之前的按鍵操作是干擾信號(hào),回到S0。在S2狀態(tài)中,如果輸入信號(hào)是1,則回到S0,表示按鍵短按已經(jīng)釋放;如果按鍵沒(méi)有釋放,輸入為0時(shí),就開(kāi)始計(jì)時(shí),計(jì)時(shí)沒(méi)有結(jié)束前一直在S2,當(dāng)計(jì)時(shí)結(jié)束了,轉(zhuǎn)入S3,表示按鍵一直按著,為長(zhǎng)按功能,在S2計(jì)時(shí)過(guò)程中,輸入從0變?yōu)?也會(huì)回到S0。在S3狀態(tài)中,輸入信號(hào)為1,返回S0,表示按鍵長(zhǎng)按釋放;輸入信號(hào)為0,執(zhí)行相應(yīng)的按鍵程序,也可以計(jì)時(shí),等計(jì)時(shí)結(jié)束執(zhí)行按鍵程序,達(dá)到按鍵連擊的功能。這就是采用狀態(tài)機(jī)進(jìn)行按鍵檢測(cè)達(dá)到短按與長(zhǎng)按的整個(gè)過(guò)程。
下面以四個(gè)按鍵接在P1的P1.7、P1.6、P1.5、P1.4,設(shè)計(jì)狀態(tài)機(jī)按鍵掃描程序。
程序代碼如下:
#define S0 0 //狀態(tài)0
#define S1 1 //狀態(tài)1
#define S2 2 //狀態(tài)2
#define S3 3 //狀態(tài)3
void key()
{static unsigned char state=S0,key_time;
unsigned char key;
key=P1&0xf0; //屏蔽P1低四位
switch (state) //檢測(cè)狀態(tài)
{case S0://狀態(tài)0
if(key!=0xf0)state=S1;break; //判斷輸入是否為0,為0轉(zhuǎn)入狀態(tài)1
case S1://狀態(tài)1
if(key==0xf0)state=S0; //判斷輸入是否為1,為1返回狀態(tài)0
else //否則,轉(zhuǎn)入狀態(tài)2,執(zhí)行按鍵程序
{state=S2;
switch (key)
{case 0xe0:/*按鍵1執(zhí)行程序*/break;
case 0xd0:/*按鍵2執(zhí)行程序*/break;
case 0xb0:/*按鍵3執(zhí)行程序*/break;
case 0x70:/*按鍵4執(zhí)行程序*/break;}} break;
case S2://狀態(tài)2
if(key==0xf0)state=S0;//判斷輸入是否為1,為1返回狀態(tài)0
else if(++key_time==100){key_time=0;state=S3;}break;
//否則開(kāi)始計(jì)時(shí),計(jì)時(shí)結(jié)束轉(zhuǎn)入狀態(tài)3
case S3://狀態(tài)3
if(key==0xf0)state=S0;//判斷輸入是否為1,為1返回狀態(tài)0
else if(++key_time==5)//否則開(kāi)始計(jì)時(shí),計(jì)時(shí)結(jié)束按鍵連擊
{key_time=0;
switch (key){
case 0xe0:break;
case 0xd0:break;
case 0xb0:break;
case 0x70:break;}
}break;}}
4 中斷處理按鍵消抖
通常使用的按鍵都是機(jī)械彈性按鍵,也就是輕觸開(kāi)關(guān)。機(jī)械按鍵在觸點(diǎn)的閉合和斷開(kāi)的過(guò)程中會(huì)產(chǎn)生抖動(dòng),一個(gè)按鍵在按下時(shí)不會(huì)立刻穩(wěn)定的導(dǎo)通,在釋放時(shí)也一樣,不會(huì)一下子就斷開(kāi),在按下和釋放瞬間都會(huì)有一連串的抖動(dòng)現(xiàn)象。按鍵的抖動(dòng)時(shí)間有按鍵的機(jī)械特性決定,一般情況為5ms~10ms。這種抖動(dòng)人是感覺(jué)不出來(lái)的,但是單片機(jī)的運(yùn)行速度是微秒級(jí)的,這里可以設(shè)計(jì)一個(gè)定時(shí)中斷來(lái)檢測(cè)按鍵的狀態(tài),通過(guò)定時(shí)中斷來(lái)消除按鍵抖動(dòng)問(wèn)題。因此可以把定時(shí)器的時(shí)間設(shè)置為10ms,每隔10ms進(jìn)入一次中斷檢測(cè)一次按鍵的狀態(tài)。
5 總結(jié)
本文介紹的這種以狀態(tài)機(jī)來(lái)實(shí)現(xiàn)按鍵檢測(cè)的方法,與一般的按鍵檢測(cè)方法相對(duì)比,能完成案件的多種狀態(tài)的檢測(cè),實(shí)現(xiàn)按鍵的短按和長(zhǎng)按功能。采用狀態(tài)機(jī)編寫(xiě)的按鍵程序也大大的改進(jìn)了按鍵消抖對(duì)CPU運(yùn)行時(shí)間消耗的問(wèn)題。程序代碼簡(jiǎn)單,維護(hù)方便,適用范圍廣。
參考文獻(xiàn)
[1]黃小華.單片機(jī)中的按鍵處理方法[J].電子科技,2014(19):1.
[2]陳曉麗.按鍵的多種狀態(tài)檢測(cè)及消抖處理方法[J].家電科技,2013(04):68-70.
作者單位
南昌理工學(xué)院 江西省南昌市 330044endprint