什么是狀態(tài)機:按鍵消抖實例
在編程中,狀態(tài)機是一種非常常用的設計模式,尤其在處理按鍵消抖的問題時非常有效。本文將介紹一個使用狀態(tài)機實現(xiàn)按鍵消抖的實例,并詳細講解其概念和編程思路。 狀態(tài)機的定義 狀態(tài)機是一個包含多個狀態(tài)的系統(tǒng)
在編程中,狀態(tài)機是一種非常常用的設計模式,尤其在處理按鍵消抖的問題時非常有效。本文將介紹一個使用狀態(tài)機實現(xiàn)按鍵消抖的實例,并詳細講解其概念和編程思路。
狀態(tài)機的定義
狀態(tài)機是一個包含多個狀態(tài)的系統(tǒng),根據(jù)輸入和當前狀態(tài)來決定狀態(tài)的轉(zhuǎn)移和輸出。在本例中,我們設置了4種狀態(tài),分別為A0、A1、A2、A3。初始時,狀態(tài)機處于A0狀態(tài)。
狀態(tài)機的工作原理
當掃描發(fā)現(xiàn)有鍵按下時,狀態(tài)機會根據(jù)當前狀態(tài)和鍵值進行狀態(tài)轉(zhuǎn)移。具體的轉(zhuǎn)移規(guī)則如下:
- 如果當前狀態(tài)為A0,并且檢測到有鍵按下,則轉(zhuǎn)移到A1狀態(tài)。
- 如果當前狀態(tài)為A1,并且檢測到有鍵按下,并且鍵值等于A1狀態(tài)下的鍵值,則轉(zhuǎn)移到A2狀態(tài),否則轉(zhuǎn)移到A0狀態(tài)。
- 如果當前狀態(tài)為A2,并且檢測到有鍵按下,并且鍵值等于A2狀態(tài)下的鍵值,則轉(zhuǎn)移到A3狀態(tài),并同時發(fā)出鍵按下消息或?qū)聪骆I的鍵值入隊,否則轉(zhuǎn)移到A0狀態(tài)。
- 如果當前狀態(tài)為A3,并且檢測到無鍵按下,則轉(zhuǎn)移到A0狀態(tài),并同時發(fā)出鍵彈起消息或彈起鍵的鍵值入隊。
函數(shù)介紹
在實現(xiàn)按鍵消抖的過程中,我們需要兩個函數(shù):
JianSaoMiao():用于鍵掃描獲取即時鍵值。JianChuLi(JZ):用于按鍵處理,可以放在時鐘中斷中調(diào)用。
代碼實現(xiàn)
#define Kong 0x00 //定義無鍵按下時,鍵掃描返回的值
#define A0 0
#define A1 1
#define A2 2
#define A3 3
struct {
unsigned char JianZhi; //當前鍵值
unsigned char DangQianZhuangTai; //當前狀態(tài)
} ZTJ;
void ZTJ_ChuShiHua(void) //狀態(tài)機初始化
{
ZTJ.DangQianZhuangTai A0; //初始狀態(tài)A0
ZTJ.JianZhi Kong; //鍵值為Kong
}
uchar JianSaoMiao(void) //鍵值掃描
{
uchar JianZhi;
//在此根據(jù)實際電路插入鍵值掃描程序段,鍵值存放到JianZhi
...
return (JianZhi);
}
void JianChuLi(uchar JZ)
{
switch(ZTJ.DangQianZhuangTai)
{
case A0:
{
if(JZ ! Kong)
{
ZTJ.DangQianZhuangTai A1; //有鍵按下,狀態(tài)轉(zhuǎn)移
ZTJ.JianZhi JZ; //保存當前鍵值
}
}
break;
case A1:
{
if(JZ ZTJ.JianZhi)
ZTJ.DangQianZhuangTai A2; //有鍵按下,且鍵值穩(wěn)定,狀態(tài)轉(zhuǎn)移
else
ZTJ_ChuShiHua(); //鍵值不穩(wěn),回到初始狀態(tài)A0
}
break;
case A2:
{
if(JZ ZTJ.JianZhi)
{
ZTJ.DangQianZhuangTai A3; //有鍵按下,且鍵值穩(wěn)定,狀態(tài)轉(zhuǎn)移
//在此發(fā)出鍵按下消息,或?qū)㈡I按下鍵值入鍵值隊列供后續(xù)處理
...
}
else
ZTJ_ChuShiHua(); //鍵值不穩(wěn),回到初始狀態(tài)A0
}
break;
case A3:
{
if(JZ Kong)
{
ZTJ_ChuShiHua(); //鍵已彈起,回到初始狀態(tài)A0
//在此發(fā)出鍵彈起消息,或?qū)㈡I彈起鍵值入鍵值隊列供后續(xù)處理
...
}
}
break;
default:
{
ZTJ_ChuShiHua(); //初始狀態(tài)A0
}
}
}
使用方法
在10ms的中斷中掃描并處理按鍵,只需調(diào)用:JianChuLi(JianSaoMiao()),這樣就可以完成發(fā)出鍵按下或鍵彈起的消息,或?qū)㈡I值送入鍵值隊列供后續(xù)處理。