2016 - 2024

感恩一路有你

什么是状态机:按键消抖实例

浏览量:2756 时间:2024-01-24 20:56:19 作者:采采

在编程中,状态机是一种非常常用的设计模式,尤其在处理按键消抖的问题时非常有效。本文将介绍一个使用状态机实现按键消抖的实例,并详细讲解其概念和编程思路。

状态机的定义

状态机是一个包含多个状态的系统,根据输入和当前状态来决定状态的转移和输出。在本例中,我们设置了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()),这样就可以完成发出键按下或键弹起的消息,或将键值送入键值队列供后续处理。

版权声明:本文内容由互联网用户自发贡献,本站不承担相关法律责任.如有侵权/违法内容,本站将立刻删除。