[APM32E0] 状态机方式实现按键处理

[复制链接]
664|39
阳光爆裂 发表于 2025-11-28 23:45 | 显示全部楼层 |阅读模式
关于状态机的一个极度确切的描述是它是一个有向图形,由一组节点和一组相应的转移函数组成。状态机通过响应一系列事件而“运行”。每个事件都在属于“当前” 节点的转移函数的控制范围内,其中函数的范围是节点的一个子集。函数返回“下一个”(也许是同一个)节点。这些节点中至少有一个必须是终态。当到达终态, 状态机停止。
有限状态机FSM思想广泛应用于硬件控制电路设计,也是软件上常用的一种处理方法(软件上称为FMM--有限消息机)。它把复杂的控制逻辑分解成有限个稳定状态,在每个状态上判断事件,变连续处理为离散数字处理,符合计算机的工作特点。同时,因为有限状态机具有有限个状态,所以可以在实际的工程上实现。但这并不意味着其只能进行有限次的处理,相反,有限状态机是闭环系统,有限无穷,可以用有限的状态,处理无穷的事务。
本次实现对按键的状态采集,以及相应状态下的LED指示动作都充分采用了状态机的编程思想,具体的就让代码来说话吧:
按键扫描头文件:定义了按键状态及相关标志位的宏定义:
  1. #ifndef _KEYSCANDRIVE_H
  2. #define _KEYSCANDRIVE_H

  3. #define KEY_DOWN 0
  4. #define KEY_DOWN_UP 1

  5. extern uint8 KeyStateFlag;      /* 按键状态 标志*/
  6. extern uint8 KEY_State;
  7. /* 按键状态 begin */
  8. #define Keystate0   0   //未按下
  9. #define Keystate1   1   //发现按下
  10. #define Keystate2   2   //稳定按下
  11. #define Keystate3   3   //释放
  12. /* 按键状态 end */

  13. extern void KeyStateScan(void);   /*按键扫描状态机*/
  14. #endif
按键扫描的函数主体:
  1. #include "includes.h"
  2. uint8 KeyStateFlag;           /* 按键状态 标志*/
  3. uint8 KEY_State;
  4. /****************************************************************************
  5. *函数名称:void KeyStateScan(void)
  6. *函数功能: 矩阵按键扫描状态机 ,对应按键控制LED
  7. *日期:2015 4 2
  8. *版本:V1.0
  9. *作者:yrj
  10. ****************************************************************************/
  11. void KeyStateScan(void)
  12. {
  13. switch (KeyStateFlag)
  14.   {
  15.     case Keystate0:  /*未按下*/
  16.       if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)== TRUE)  /*未按下*/
  17.       { KeyStateFlag = Keystate0; }
  18.       else                  /* 按下 */
  19.       {  KeyStateFlag = Keystate1; }
  20.       break;
  21.     case Keystate1: /*发现按下*/
  22.       if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)==TRUE)  /*未按下*/
  23.       { KeyStateFlag = Keystate0; }
  24.       else                  /* 按下 */
  25.       { KeyStateFlag= Keystate2;  }
  26.       break;  
  27.     case Keystate2: /*稳定按下*/
  28.       if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)==TRUE)    /*未按下*/
  29.       {  KeyStateFlag= Keystate0;     }
  30.       else                  /* 按下 */
  31.       {
  32.          KeyStateFlag= Keystate3; //保持
  33.          KEY_State=KEY_DOWN;    /* 按键按下 */
  34.       }
  35.       break;
  36.     case Keystate3: /*释放*/
  37.       {
  38.         if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)==TRUE)   /*未按下*/
  39.         {
  40.           KeyStateFlag= Keystate0;
  41.           KEY_State=KEY_DOWN_UP;    /* 按键按下并抬起*/
  42.         }aaa
  43.       }     
  44.       break;
  45.     default:
  46.       {KeyStateFlag= Keystate0;}
  47.       break;
  48.   }   
  49. }
main函数主体:
  1. void main(void)  
  2. {   
  3.   bsp_init( );   
  4.   while(1)     
  5.   {   
  6.     KeyStateScan( ); /* 按键状态扫描 */  
  7.     switch(KEY_State)  
  8.     {  
  9.     case KEY_DOWN :  
  10.         LED_ON(); break;  
  11.     case KEY_DOWN_UP :  
  12.         LED_OFF(); break;  
  13.       default :break;  
  14.    }  
  15. }







天鹅绒星星 发表于 2025-12-1 22:38 | 显示全部楼层
像按键这种使用状态机实现还是比较合适的。
霜咬回响 发表于 2025-12-2 16:35 | 显示全部楼层
这个状态机思想还是挺好的
星云狂想曲 发表于 2025-12-3 14:20 | 显示全部楼层
这个状态机没有对释放进行二次确认呀
51xlf 发表于 2025-12-3 23:01 | 显示全部楼层
分状态响应电平变化,通过定时器扫描消除抖动
涡流远见者 发表于 2025-12-4 09:24 | 显示全部楼层
这个状态机有点简单了。楼主再努力努力,写一个带有双击检测的吧
macpherson 发表于 2025-12-4 20:04 | 显示全部楼层
核心优势是逻辑清晰、抗干扰强、可扩展
jackcat 发表于 2025-12-4 22:59 | 显示全部楼层
适用于需要消抖、长按、短按、组合键等复杂功能
sheflynn 发表于 2025-12-5 10:53 | 显示全部楼层
若周期不稳定,可能导致长按/短按判断错误。
phoenixwhite 发表于 2025-12-5 14:40 | 显示全部楼层
状态机方式是单片机按键处理的最优方案之一
sdCAD 发表于 2025-12-5 16:38 | 显示全部楼层
按键状态机通常包含以下核心状态

STATE_IDLE按键未按下,等待触发。
STATE_DEBOUNCE_PRESS检测到按键按下,需消抖确认。
STATE_PRESS_DOWN按键已稳定按下,可触发短按或进入长按检测。
STATE_DEBOUNCE_RELEASE检测到按键释放,需消抖确认。
STATE_LONG_PRESS按键持续按下超过阈值时间,触发长按事件。
louliana 发表于 2025-12-5 20:43 | 显示全部楼层
状态机通过定义明确的按键状态和转移条件,避免了传统轮询或中断方式的逻辑混乱
jtracy3 发表于 2025-12-6 10:28 | 显示全部楼层
硬件消抖 + 软件消抖结合更可靠
wengh2016 发表于 2025-12-6 15:15 | 显示全部楼层
支持多个按键,可为每个按键定义独立的状态机实例,或使用结构体数组管理。
yeates333 发表于 2025-12-6 19:05 | 显示全部楼层
按键处理的核心是通过 “状态迁移” 响应按键的电平变化,避免单次电平检测导致的抖动误触发。
lzbf 发表于 2025-12-6 22:59 | 显示全部楼层
通过状态定义→事件触发→转移逻辑→动作执行四步,可优雅解决抖动、多事件识别等问题
fengm 发表于 2025-12-7 09:35 | 显示全部楼层
实现按键处理是一种高效、可靠的方法
rosemoore 发表于 2025-12-7 13:17 | 显示全部楼层
采用状态机处理按键,不仅能提升产品稳定性,还能为后续功能迭代打下良好基础
eefas 发表于 2025-12-7 17:36 | 显示全部楼层
为什么用状态机处理按键?              
bestwell 发表于 2025-12-7 20:53 | 显示全部楼层
状态机通过定义有限状态和状态转移条件,将按键的机械抖动、按下、保持、释放等过程转化为有序的状态切换,从而实现稳定、可靠的按键检测与事件触发。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

68

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部
0