- 原創 https://jingyan.baidu.com/article/14bd256e112e25bb6d261211.html
貌似沒有教程講到過狀態機的概念和編程思路,特從別的論壇轉貼一篇很好的實例,獻給廣大初學者。用狀態機做鍵盤消抖,很好用,不必延時等待鍵盤穩定,當檢測到有鍵按下或彈起時能發出相應的鍵盤消息
步驟/方法
-
設置狀態機有4種狀態,A0,A1,A2,A3
初始時處於A0狀態,當掃描發現有鍵按下時,轉入到A1狀態。
當處於A1狀態時,當掃描發現有鍵按下並且鍵值等於A1狀態下的鍵值時,轉入到A2狀態,否則轉入A0狀態。
當處於A2狀態時,當掃描發現有鍵按下並且鍵值等於A2狀態下的鍵值時,轉入到A3狀態,同時發出鍵按下消息或將按下鍵的鍵值入隊,否則轉入A0狀態。
當處於A3狀態時,當掃描發現無鍵按下時,轉入到A0狀態。同時發出鍵彈起消息或彈起鍵的鍵值入隊。
函數JianSaoMiao()用於鍵掃描的到即時鍵值
函數JianChuLi()用於按鍵處理,可放在時鍾中斷中調用
例:在10ms中斷中掃描並處理按鍵只需調用:JianChuLi(JianSaoMiao());
可使調用后完成發出鍵按下或鍵彈起的消息,或者將鍵值送入鍵值隊列供后續處理 -
#define Kong 0x00 //定義無鍵按下時,鍵掃描返回的值
#define A0 0
#define A1 1
#define A2 2
#define A3 3
struct
{
unsigned char JianZhi; //當前鍵值
unsigned char DangQianZhuangTai;//當前狀態
} ZTJ;
void ZTJ_ChuShiHua(void) //狀態機初始化
{
ZTJ.DangQianZhuangTai=A0; //初始狀態A0
ZTJ.JianZhi=Kong; //鍵值為Kong
}
uchar JianSaoMiao(void) //鍵值掃描
{
uchar JianZhi;
//在此根據實際電路插入鍵值掃描程序段,鍵值存放到JianZhi
......
return(JianZhi);
}
void JianChuLi(uchar JZ)
{
switch(ZTJ.DangQianZhuangTai)
{
case A0:
{
if(JZ!=Kong)
{
ZTJ.DangQianZhuangTai=A1; //有鍵按下,狀態轉移
ZTJ.JianZhi=JZ; //保存當前鍵值
}
} break;
case A1:
{
if(JZ==ZTJ.JianZhi)
ZTJ.DangQianZhuangTai=A2; //有鍵按下,且鍵值穩定狀態轉移
else
ZTJ_ChuShiHua(); //鍵值不穩,回到初始狀態A0
} break;
case A2:
{
if(JZ==ZTJ.JianZhi)
{
ZTJ.DangQianZhuangTai=A3; //有鍵按下,且鍵值穩定狀態轉移
//在此發出鍵按下消息,或將鍵按下鍵值入鍵值隊列供后續處理
......
}
else
ZTJ_ChuShiHua(); //鍵值不穩,回到初始狀態A0
} break;
case A3:
{
if(JZ==Kong)
{
ZTJ_ChuShiHua(); //鍵已彈起,回到初始狀態A0
//在此發出鍵彈起消息,或將鍵彈起鍵值入鍵值隊列供后續處理
......
}
} break;
default :
{
ZTJ_ChuShiHua(); //初始狀態A0
}
}
}
