简单地用状态机写的按键检测

本文介绍了一种基于状态机的STM32按键检测方法,该方法能够有效地利用CPU资源并减少误判。通过实现一个具体的状态机示例,演示了如何在不同按键状态下进行LED的反转控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在优快云上写的第一篇文章,,,,

 

之前就听说过状态机,但并没有感觉到其比普通按键的优越之处。

 

接触了实时操作系统之后,才领悟到这种按键检测方法可以很好地利用CPU的资源(或者说不用实时操作系统时更体现优越性)

 

 

这里直接粘贴按键检测的代码了(按键、LED初始化、UCOS系统就不赘述了)

 

程序是STM32F103的,不过和芯片类型关系不大

 

void key0_task(void *pdata)
{
 while(1)
 {
  key0_scan();
  key1_scan();
  key2_scan();
  delay_ms(5);   //前提是UCOS时钟节拍为5ms,以10ms为一个状态检测消抖;
 };
}

enum key0_states_e
{
 KEY_S1,                // button 0 is not pressed
 KEY_S2,                //Button 0 has been pressed
 KEY_S3,                 //Button 0 are pressing
 KEY_S4,                 //Button 0 has been lossen
};

void key0_scan(void)
{
 static enum key0_states_e key0_state=KEY_S1;
 static int press0=0;
 switch(key0_state)
 {
 case KEY_S1:
   
   if(KEY0==0)
    {
     key0_state = KEY_S2;
    }
   break;
 case KEY_S2:
   
    {
     if(KEY0==0)
     {
      press0++;
      key0_state = KEY_S3;
     }
     else
      key0_state = KEY_S1;
    }
     break;
 case KEY_S3:
   {
    if(KEY0==0)
    {
     press0++;
     key0_state = KEY_S3;
    }
    else
    {
     key0_state = KEY_S4;
    }
   }
   break;
 case KEY_S4:
   {
    if(press0>200)
    {
     LED0=!LED0;
     LED1=!LED1;
    }
    else
     LED0=!LED0;
    press0=0;
    key0_state=KEY_S1;
   }
   break;
 }
} 

 

程序实现的功能:按键按下2s以内,LED0反转;2s以上,LED1和LED0都反转

 

 

多说一句,10ms的消抖检测真的是最合适的,lz之前没写那句delay_ms(5),结果用按键控制各种不灵。

初写文章,希望大佬们多多批评指正。

当然可以!以下是一个简单的使用状态机实现按键检测的示例代码: ```c #include <stdio.h> #include <stdbool.h> // 按键状态枚举 typedef enum { RELEASED, PRESSED } ButtonState; // 按键检测状态机 typedef struct { ButtonState currentState; ButtonState previousState; } ButtonFSM; // 初始化状态机 void buttonFSMInit(ButtonFSM* fsm) { fsm->currentState = RELEASED; fsm->previousState = RELEASED; } // 更新状态机 void buttonFSMUpdate(ButtonFSM* fsm, bool isPressed) { fsm->previousState = fsm->currentState; if (isPressed) { fsm->currentState = PRESSED; } else { fsm->currentState = RELEASED; } } // 检测按键状态变化 void checkButtonStateChange(ButtonFSM* fsm) { if (fsm->currentState != fsm->previousState) { if (fsm->currentState == PRESSED) { printf("按键按下\n"); } else { printf("按键松开\n"); } } } int main() { ButtonFSM button; buttonFSMInit(&button); // 模拟按键状态变化 bool isButtonPressed = false; // 模拟按键检测循环 for (int i = 0; i < 10; i++) { // 假设每次循环都检测一次按键状态 buttonFSMUpdate(&button, isButtonPressed); checkButtonStateChange(&button); // 等待一段时间 // ... // 模拟按键状态变化 isButtonPressed = !isButtonPressed; } return 0; } ``` 这个示例代码中,我们定义了一个按键状态枚举(`ButtonState`),表示按键的两种状态:按下和松开。然后,我们定义了一个按键检测状态机(`ButtonFSM`),包含当前状态和前一个状态。通过 `buttonFSMInit` 函数进行初始化,`buttonFSMUpdate` 函数更新状态机,`checkButtonStateChange` 函数检测按键状态变化。 在 `main` 函数中,我们模拟了按键状态的变化,并通过循环检测按键状态的变化情况。你可以根据实际需求修改循环部分的代码,并在按键状态变化时执行相应的操作。 希望这个示例能够帮到你!如果你有任何疑问,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值