当前位置: 首页 > article >正文

专项:STM32状态机结构简述

前言

在 STM32 开发中,状态机是一种常用的编程结构,用于处理复杂的逻辑流程和事件驱动的系统。状态机通过定义不同的状态以及状态之间的转换条件,使得程序逻辑更加清晰、易于维护和扩展。如果没有自己的编程习惯,可以使用状态机结构编程。

基本结构

1. 状态(State)

状态是状态机在某一时刻所处的情况。例如,在 LED 亮灭控制状态机中,有led亮和led灭两个状态[struct{on,off};],每个状态都有其特定的行为控制和可能的转换方式。

2. 事件(Event)

事件是触发状态转换的条件(类似于QT信号传递)。它可以是外部输入(如按键按下、传感器信号变化)、定时器超时等。例如,在 LED 控制状态机中,“按下按键” 这个事件可以触发从 “LED 熄灭” 状态转换到 “LED 点亮” 状态[if(key==1){state=on}else{state=off}]。

3. 转换(Transition)

转换定义了状态之间的迁移规则,即当某个事件发生时,状态机从一个状态转换到另一个状态[state=on/state=off]。每个转换都与一个特定的事件相关联。

4. 动作(Action)

动作是状态机在进入某个状态、离开某个状态或在状态转换过程中执行的操作(执行事件)。例如,在进入 “LED 点亮” 状态时,执行点亮 LED 的操作。

实现方式

1. 枚举定义状态

使用枚举类型来定义状态机的所有可能状态[不可使用{1,2,3,4}这种定义,维护比较困难]。

typedef enum {
    STATE_IDLE,      // 空闲
    STATE_RUNNING,   // 运行
    STATE_ERROR      // 错误
} State_t;
2. 状态处理函数

为每个状态编写对应的处理函数(事件),这些函数负责处理该状态下的具体操作和状态转换逻辑。

//空闲
void StateIdleHandler(void) {
    if (events1()) {
        //其他需要执行的事件
        currentState = STATE_RUNNING; // 转换到运行状态
    }
}

//运行
void StateRunningHandler(void) {
    if (events2()) {
        //运行事件
        currentState = STATE_ERROR; // 如果错误转换到错误状态,没有的话进进入正常状态机
    }
}

//错误
void StateErrorHandler(void) {
    TurnOnErrorLED();
    // 错误处理
    if (errorevents()) {//处理完成,进入空闲
        currentState = STATE_IDLE; // 转换到空闲状态
    }
}
3. 主循环中的状态机调度

在main中,根据当前状态调用相应的状态处理函数。

State_t currentState = STATE_IDLE;//在系统启动时,自动进入一个待机状态

int main(void) {
    while (1) {
        switch (currentState) {//状态机切换状态。
            case STATE_IDLE:
                StateIdleHandler();
                break;
            case STATE_RUNNING:
                StateRunningHandler();
                break;
            case STATE_ERROR:
                StateErrorHandler();
                break;
            default:
                // 处理未知状态,最后回到状态中,不能死循环
                break;
        }
    }
}

总结

通过状态机结构,可以将复杂的系统逻辑分解为多个简单的状态和状态转换,使得代码的可读性和可维护性大大提高。在 STM32 开发中,状态机常用于处理按键输入、传感器数据处理、通信协议解析等场景,使用和学习中尽量多使用状态机模式。


http://www.kler.cn/a/573093.html

相关文章:

  • Stable Diffusion模型采样方法与参数配置详解(含步数及画风适配表)
  • 在Linux中开发OpenGL——环境搭建
  • 【BFS最短路问题】最小基因变化
  • 服务器数据恢复—raid5阵列中硬盘掉线导致上层应用不可用的数据恢复案例
  • 【MySQL】与MongoDB的区别,字符集,三范式,存储引擎InnoDB、MyISAM
  • 优化cache利用、减少cache miss的方法
  • LLM 模型 Prompt 工程
  • [Computer Vision]图像分割技术
  • Android10.0关于发送广播Sending non-protected broadcast android.price.public.close
  • JVM(Java Virtual Machine,Java 虚拟机)的作用
  • 机器分类的基石:逻辑回归Logistic Regression
  • JavaWeb-HttpServlet源码分析
  • SpringBoot为什么要禁止循环依赖?
  • 网络安全公钥密码体制
  • 不懂ui->layout()->removeWidget(bar);
  • 2W8000字 LLM架构文章阅读指北
  • 题目梳理2025[长期更新]
  • 在阿里云ECS云服务器上安装、配置及高效使用Docker与Docker Compose
  • 数字北极星与DeepSeek深度融合,引领流程智能的AI革命
  • 第十二届蓝桥杯大学A组java省赛答案整理