什么是状态机:按键消抖实例
在编程中,状态机是一种非常常用的设计模式,尤其在处理按键消抖的问题时非常有效。本文将介绍一个使用状态机实现按键消抖的实例,并详细讲解其概念和编程思路。 状态机的定义 状态机是一个包含多个状态的系统
在编程中,状态机是一种非常常用的设计模式,尤其在处理按键消抖的问题时非常有效。本文将介绍一个使用状态机实现按键消抖的实例,并详细讲解其概念和编程思路。
状态机的定义
状态机是一个包含多个状态的系统,根据输入和当前状态来决定状态的转移和输出。在本例中,我们设置了4种状态,分别为A0、A1、A2、A3。初始时,状态机处于A0状态。
状态机的工作原理
当扫描发现有键按下时,状态机会根据当前状态和键值进行状态转移。具体的转移规则如下:
- 如果当前状态为A0,并且检测到有键按下,则转移到A1状态。
- 如果当前状态为A1,并且检测到有键按下,并且键值等于A1状态下的键值,则转移到A2状态,否则转移到A0状态。
- 如果当前状态为A2,并且检测到有键按下,并且键值等于A2状态下的键值,则转移到A3状态,并同时发出键按下消息或将按下键的键值入队,否则转移到A0状态。
- 如果当前状态为A3,并且检测到无键按下,则转移到A0状态,并同时发出键弹起消息或弹起键的键值入队。
函数介绍
在实现按键消抖的过程中,我们需要两个函数:
JianSaoMiao():用于键扫描获取即时键值。JianChuLi(JZ):用于按键处理,可以放在时钟中断中调用。
代码实现
#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
}
}
}
使用方法
在10ms的中断中扫描并处理按键,只需调用:JianChuLi(JianSaoMiao()),这样就可以完成发出键按下或键弹起的消息,或将键值送入键值队列供后续处理。