打印
[APM32F4]

状态机简介及编程-1

[复制链接]
647|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 lzh12a3nf 于 2024-2-28 22:23 编辑

#申请原创#@21小跑堂
1、前言

最近在学习过程中运用到了状态机的思维,此文将对状态机的概念及使用进行学习记录。欢迎大家一起学习,有问题评论区一起讨论。

2、状态机
  • 概念:状态机,又称为有限状态机(Finite State Machine,FSM),是一种用于设计和实现程序和系统行为的模型。
  • 涉及六个元素:起始状态、结束状态、现状态、目标状态、动作、条件。
  • 涉及实现流程:
      a.定义状态和事件:首先,需要定义系统可能处于的所有状态,以及可能触发状态转换的事件。
      b.创建状态转换逻辑:确定每个状态下,对于不同事件应该如何响应,包括状态转换和执行的动作。
      c.实现状态机逻辑:编写代码来实现状态转换和动作执行。这通常涉及到编写一个主循环(main loop),在其中不断检查事件并更新状态。
      d.将实现的状态机代码集成到MCU平台(APM32系列)中。其中,可涉及:按键、定时器、中断、输入输出等
      e.调试和测试:状态机设计完成后,搭载上APM32的平台上,需进行硬件的调试和测试,确保状态机的转换能正常工作。

  • 状态机实现的基本逻辑图:
      这是一个简单的状态机,含有两个状态:①开门,人进入,关门。②关门,刷卡,开门。


  • MCU(APM32)的状态机
       举个简单的例子:就按键处理来说,按键动作本身也可以看做一个状态机。一个细小的击键动作包含了:释放、抖动、按下、抖动和重新释放等状态
  • 状态机语句框架
       在日常编码中,状态机的思想经常使用,如下:
       a.if....else....语句状态机
if 状态1
else if 状态2
else if 状态3
...
else 状态n
      优点:
             1、该语句结构能够处理更复杂的条件判断,不仅仅限于常量或枚举的比较,还可以包含范围判断、复合条件等。
             2、逻辑简单易懂
      缺点:
              1、当状态或条件较多时,效率下降,需逐一评估条件直到找到匹配项。
              2、随着条件的增加,逻辑容易变得非常复杂。

       b.switch....case....语句状态机
 switch(state)
      优点:
             1、对基于枚举或整数的状态机,效率更高。
             2、清晰的分支结构,使得各个状态和转换逻辑更加明确。
             3、添加或删除状态时,代码修改更集中,不易混乱。
      缺点:
             1、仅适用于有限的数据类型(如整数、枚举等),且不能直接使用范围或复合条件。



3、状态机设计
下面,我将基于上个章节的状态机拓展,进行逻辑代码框图设计及代码实现。
3.1、状态机实现逻辑图


3.2、参数说明:

存在状态:
  • 开门,人进入,关门。
  • 开门,刷卡,提示门已开。
  • 关门,刷卡,开门。
  • 关门,强制进入,警告需刷卡。
状态设置:

  • 使用自定义枚举DoorState、DoorEvent将状态列举出来。
状态转换:使用handleEvent回调函数,函数内设计switch....case....语句进行状态转换。


3.3、状态机逻辑代码实现

#include <stdio.h>
#include <stdbool.h>

// 定义电闸门状态
typedef enum {
    DOOR_CLOSED,
    DOOR_OPEN
} DoorState;

// 电闸门事件
typedef enum {
    CARD_SWIPED,
    PERSON_PASSED,
    NO_ACTION
} DoorEvent;

// 状态机处理函数原型
void handleEvent(DoorState* state, DoorEvent event);

// 主程序入口
int main() {
    DoorState state = DOOR_CLOSED; // 初始状态设置为门关闭
    DoorEvent event;

    // 模仿事件触发
    // 情景1: 刷卡时门关闭
    event = CARD_SWIPED;
    handleEvent(&state, event);

    // 情景2: 关闭状态下未刷卡(触发警报)
    event = NO_ACTION;
    handleEvent(&state, event);

    // 情景3: 开门状态下人通过
    event = PERSON_PASSED;
    handleEvent(&state, event);

    // 情景4: 开门状态下再次刷卡
    event = CARD_SWIPED;
    handleEvent(&state, event);

    return 0;
}

void handleEvent(DoorState* state, DoorEvent event) {
    switch (*state) {
        case DOOR_CLOSED:
            if (event == CARD_SWIPED) {
                *state = DOOR_OPEN; // 改变状态为门打开
                printf("门现在打开。\n");
            }
            else if (event == NO_ACTION) {
                printf("警告!请刷卡!\n"); // 保持状态,只是给出警告
            }
            break;
        case DOOR_OPEN:
            if (event == PERSON_PASSED) {
                *state = DOOR_CLOSED; // 改变状态为门关闭
                printf("人已进入,门现在关闭。\n");
            }
            else if (event == CARD_SWIPED) {
                printf("门已经打开。\n"); // 保持门开状态
            }
            break;
        default:
            printf("未知状态.\n");
            break;
    }
}

注:

  • 本次文章内容分享到此,下一章节将基于APM32系列开发板,实现状态机转换代码。
  • 如有问题,大家评论区一起讨论,谢谢。








使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

37

帖子

0

粉丝