[C]精炼分析状态机FSM

news2024/11/24 20:39:22

FSM:finite state machine  【有限状态机】,用通俗的语言来表达就是逻辑流程图。

当前状态满足触发条件时,就会切换到下一个状态,并执行对应的任务操作。传统代码做法是用if-else 或者 switch-case来处理。若要做到可扩展性良好的话,就需用状态表来设计。

用一句代码表达状态机原理:

if( state==CurrState && Event==True )
{
   state = NextState;
   Action();
}

举个简单的例子:某个电子设备的模式运行切换逻辑如下:

当前状态(CurrState)

触发条件(Event)

下个状态(Next)

执行动作(Action)

M_IDLE 

按钮1按下

MODE1

亮红灯,蜂鸣器响1

M_IDLE 

按钮2按下

MODE2

(无动作)

MODE1

运行10秒后

MODE3

亮绿灯,电机转速100

MODE2

运行5秒后和温度大于40

M_IDLE

亮蓝灯,电机转速300

MODE3

运行30

M_END

关灯,关电机

M_END

按钮1按下和按钮2按下

M_IDLE

蜂鸣器响2

 

C语言写的伪代码,传统方法:

#define M_IDLE 0
#define MODE1 1
#define MODE2 2
#define MODE3 3
#define M_END 4
int state_mode = M_IDLE;
int run_cnt = 0;
int cur_temp = 0;
int btn1 = 0;
int btn2 = 0;

void main()
{
    while (1)
    {
        switch (state_mode)
        {
        case M_IDLE:
            if (btn1)
            {
                state_mode = MODE1;
                light_red();
                beep_cnt(1);
            }
            if (btn2)
            {
                state_mode = MODE2;
            }
            break;

        case MODE1:
            if (run_cnt >= 10)
            {
                state_mode = MODE3;
                light_green();
                motor_speed(100);
            }
            break;

        case MODE2:
            if (run_cnt >= 5 && cur_temp > 40)
            {
                state_mode = M_IDLE;
                light_blue();
                motor_speed(300);
            }
            break;

        case MODE3:
            if (run_cnt > 30)
            {
                state_mode = M_END;
                light_off();
                motor_off();
            }
            break;

        case M_END:
            if (btn1 && btn2)
            {
                state_mode = M_IDLE;
                beep_cnt(2);
            }
            break;
        }
    }
}

C语言写的伪代码,状态机表格方法:

#include<stdio.h>

int run_cnt = 0;
int cur_temp = 0;
int btn1 = 0;
int btn2 = 0;

typedef enum
{
   M_IDLE,
   MODE1,
   MODE2,
   MODE3,
   M_END
}EnumState;

int state_mode = M_IDLE;

typedef struct
{
  EnumState curr_state;//当前状态
  int(*event_condition)();//触发事件条件
  EnumState next_state;//下一状态
  void(*action)();//执行动作
}FSM_Table;

//状态切换事件条件
int event_condition0()
{
  if(btn1==1)
    return 1;
  return 0;
}
//状态切换触发后并执行的操作
void action0()
{
  light_red();
  beep_cnt(1);
}

int event_condition0b()
{
  if(btn2==1)
    return 1;
  return 0;
}

void none_action()
{
 //没有动作
}

int event_condition1()
{
    return(run_cnt>=10);
}
void action1()
{
    light_green();
    motor_speed(100);
    printf("Runing action1\n");
}


int event_condition2()
{
   return(run_cnt>5 && cur_temp>40);

}
void action2()
{
    light_blue();
    motor_speed(300);
    printf("Runing action2\n");
}

int event_condition3()
{
   return(run_cnt>30);
}
void action3()
{
    light_off();
    motor_off();
}

int event_condition_end()
{
    return(btn1&&btn2);
}
void action_end()
{
    beep_cnt(2);
}


FSM_Table fsm_list[]=
{
   {M_IDLE,event_condition0,MODE1,action0},
   {M_IDLE,event_condition0b,MODE2,none_action},
   {MODE1,event_condition1,MODE3,action1},
   {MODE2,event_condition2,M_IDLE,action2},
   {MODE3,event_condition3,M_END,action3},
   {M_END,event_condition_end,M_IDLE,action_end},
};



void main()
{

   int table_size = sizeof(fsm_list)/sizeof(FSM_Table);
   printf("fsm_size=%d.\n",table_size);
    while(1)
    {
        for (size_t i = 0; i < table_size; i++)
        {
            if(state_mode==fsm_list[i].curr_state&&fsm_list[i].event_condition())
            {
                state_mode = fsm_list[i].next_state;
                fsm_list[i].action();
            }
        }
    }
}

经过这两种代码方法和思路的对比,可以看出,采用状态机数据结构表方案会十分的清晰贴合excel表上列举的功能思维,而且若后面扩展功能也十分的方便,只需要添加函数和关系表。

尤其当逻辑流程比较复杂多变时,用状态机表格的优势会比较突出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1036904.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【车联网/自动驾驶仿真学习】VEINS_CARLA安装指南

VEINS_CARLA安装指南 这是Veins团队开发的一个接口&#xff0c;能够实现veins和carla之间的数据传输&#xff0c;通过veins通信模块能够实现carla中感知决策等相关数据的传输。 github:veins_carlapaper:Poster: A Case for Heterogenous Co-Simulation of Cooperative and A…

MySQL 高级(进阶) SQL 语句(二) -----连接查询、union联集、case、正则表达式

目录 1 连接查询 1.1 内连接 1.2 左连接 1.3 右连接 2 UNION ----联集 2.1 交集值 2.2 无交集值 3 case 4 正则表达式 1 连接查询 准备工作&#xff1a; create database k1; use k1; create table location (Region char(20),Store_Name char(20)); insert into loca…

最新时间注入攻击和代码分析技术

点击星标&#xff0c;即时接收最新推文 本文选自《web安全攻防渗透测试实战指南&#xff08;第2版&#xff09;》 点击图片五折购书 时间注入攻击 时间注入攻击的测试地址在本书第2章。 访问该网址时&#xff0c;页面返回yes&#xff1b;在网址的后面加上一个单引号&#xff0c…

《从菜鸟到大师之路 Nginx 篇》

《从菜鸟到大师之路 Nginx 篇》 Nginx 简介 Nginx 是开源、高性能、高可靠的 Web 和反向代理服务器&#xff0c;而且支持热部署&#xff0c;几乎可以做到 7 * 24 小时不间断运行&#xff0c;即使运行几个月也不需要重新启动&#xff0c;还能在不间断服务的情况下对软件版本进行…

java面试题-学成在线项目

1、详细说说你的项目吧 从以下几个方面进行项目介绍&#xff1a; 1、项目的背景&#xff0c;包括&#xff1a;是自研还是外包、什么业务、服务的客户群是谁、谁去运营等问题。 2、项目的业务流程 3、项目的功能模块 4、项目的技术架构 5、个人工作职责 6、个人负责模块的详细说…

R统计绘图-线性混合效应模型详解(理论、模型构建、检验、选择、方差分解及结果可视化)

目录 一、 基础理论 二、数据准备 三、构建线性混合效应模型(LMMs) 3.1 lme4线性混合效应模型formula 3.2 随机截距模型构建及检验 3.3 随机截距模型分析结果解释及可视化 3.4 随机斜率模型构建、检验及可视化 四、线性混合效应模型选择 4.1 多模型比较 4.2 模型最优子…

003-第一代硬件系统环境搭建

第一代硬件系统环境搭建 文章目录 第一代硬件系统环境搭建项目介绍摘要结构部分电路部分软件部分 关键字&#xff1a; Qt、 Qml、 硬件、 系统、 搭建 项目介绍 欢迎来到我们的 QML & C 项目&#xff01;这个项目结合了 QML&#xff08;Qt Meta-Object Language&#…

Java编程的精髓:深入理解JVM和性能优化

文章目录 Java虚拟机&#xff08;JVM&#xff09;的核心概念1. 类加载器&#xff08;Class Loader&#xff09;2. 内存区域3. 垃圾回收&#xff08;Garbage Collection&#xff09;4. 类型转换和多态 JVM性能调优1. JVM参数调整2. 内存管理3. 多线程优化4. 使用性能分析工具5. …

服务注册发现_创建服务消费者

创建cloud-consumer-order80模块 pom文件添加依赖 <dependencies><!-- 引入Eureka client依赖 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId&…

CompletableFuture-FutureTask结合线程池提升性能

使用线程池&#xff1a; 返回计算结果&#xff1a; 2.2.3 Future编码实战和优缺点分析 优点&#xff1a;Future线程池异步多线程任务配合&#xff0c;能显著提高程序的运行效率。 缺点&#xff1a; get()阻塞---一旦调用get()方法求结果&#xff0c;一旦调用不见不散&…

GEE:哨兵时间序列遥感数据和动态阈值方法计算物候时期EOS/SOS(2)

作者:CSDN @ _养乐多_ 本文将分享和解释论文《Improved Estimates of Arctic Land Surface Phenology Using Sentinel-2 Time Series》中使用到的基于阈值估算北极地区的植被物候,特别是北极地区的植被季节开始和结束的日期(SoS和EoS)的方法和代码。该方法使用的是使用哨兵…

Pytorch(GPU)环境安装

winR:启动cmd; 输入nvidia-smi 查看cuda的配置 (1) 安装CUDA 地址&#xff1a;https://developer.nvidia.com/cuda-downloads 详细参考&#xff1a;安装CUDA与CUDNN与Pytorch&#xff08;最新超级详细图文版本2023年8月最新&#xff09;_pytorch安装cudnn_LyaJpunov的博客-C…

Zookeeper-JavaApI操作

JavaApI操作 JavaApI操作1) Curator 介绍2) Curator API 常用操作a) 建立连接与CRUD基本操作b) Watch事件监听c) 分布式锁c.1) 介绍c.2) Zookeeper分布式锁原理c.3) 案例&#xff1a;模拟12306售票 JavaApI操作 1) Curator 介绍 Curator 是 Apache ZooKeeper 的Java客户端库。…

树结构的讲解与二叉树的基本运用

目录&#xff1a; 一&#xff0c;树的基本知识 二&#xff0c;树的类型 三&#xff0c;树的存储 四&#xff0c;树的基本运算 五&#xff0c;二叉树堆的基本运用 一&#xff0c;树的基本知识 树是一种非线性的数据结构&#xff0c;它是由n个有限结点组合而成为一个具有层次…

【1++的Linux】之进程(三)

&#x1f44d;作者主页&#xff1a;进击的1 &#x1f929; 专栏链接&#xff1a;【1的Linux】 文章目录 一&#xff0c;什么是进程地址空间&#xff1f;二&#xff0c;进程地址空间是怎么设计的&#xff1f;三&#xff0c;为什么要有进程地址空间&#xff1f; 一&#xff0c;什…

【C++杂货铺】一颗具有搜索功能的二叉树

文章目录 一、二叉搜索树概念二、二叉搜索树的操作2.1 二叉搜索树的查找2.2 二叉搜索树的插入2.3 二叉搜索树的删除 三、二叉搜索树的实现3.1 BinarySearchTreeNode&#xff08;结点类&#xff09;3.2 BinarySearchTree&#xff08;二叉搜索树类&#xff09;3.2.1 框架3.2.2 in…

【力扣485】最大连续 1 的个数

&#x1f451;专栏内容&#xff1a;力扣刷题⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;前路未远&#xff0c;步履不停 目录 一、题目描述二、题目分析1、最值模拟2、双指针 一、题目描述 题目链接&#xff1a;最大连续 1 的个数 给定一个二进制数…

辨析常见的医学数据分析(相关性分析回归分析)

目录 1 常见的三种分类结果&#xff1f; 2 什么是相关性分析&#xff1f; 相关性分析的结果怎么看&#xff1f; 3 什么是回归分析&#xff1f; 1&#xff09;前提 2&#xff09;常见的回归模型 4 对于存在对照组实验的医学病例如何分析&#xff1f; 1&#xff09;卡方检验…

万字解析30张图带你领略glibc内存管理精髓

最近在逛知乎的时候&#xff0c;看到篇帖子&#xff0c;如下&#xff1a; 看了下面所有的回答&#xff0c;要么是没有回答到点上&#xff0c;要么是回答不够深入&#xff0c;所以&#xff0c;借助本文&#xff0c;深入讲解C/C内存管理。 1 写在前面 源码分析本身就很枯燥乏味…

服务注册发现_解读Eureka注册中心UI界面

参数&#xff1a; Environment: 环境&#xff0c;默认为test&#xff0c;该参数在实际使用过程中&#xff0c;可以不用更改Data center&#xff1a; 数据中心&#xff0c;使用的是默认的是 “MyOwn”Current time&#xff1a;当前的系统时间Uptime&#xff1a;已经运行了多少时…