[C]精炼分析状态机FSM

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

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

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

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

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

当前状态(CurrState)

触发条件(Event)

下个状态(NextState)

执行动作(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.rhkb.cn/news/143590.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

正确设置PyTorch训练时使用的GPU资源

背景&#xff1a; 最近在使用Hugging Face的transformers api来进行预训练大模型的微调&#xff0c;机器是8卡的GPU&#xff0c;当我调用trainer.train()之后&#xff0c;发现8个GPU都被使用了&#xff0c;因为这个机器上面还有其他人跑的模型&#xff0c;当我进行训练的时候&…

Qt使用I.MX6U开发板上的按键(原理:将电脑键盘方向键↓在Qt中的枚举值与开发板中按键定义的枚举值一致,这样电脑端测试效果就与开发板的一致)

在上篇介绍了Qt点亮I.MX6U开发板的一个LED&#xff0c;对于Qt控制I.MX6U开发板的一个蜂鸣器原理也是一样的&#xff0c;就不做详细介绍&#xff0c;具体可参考Qt控制I.MX6U开发板的一个蜂鸣器&#xff0c;本篇介绍Qt使用I.MX6U开发板上的按键的相关内容。 文章目录 1. 开发板硬…

【Verilog 教程】6.5 Verilog避免Latch

关键词&#xff1a;触发器&#xff0c;锁存器 Latch 的含义 锁存器&#xff08;Latch&#xff09;&#xff0c;是电平触发的存储单元&#xff0c;数据存储的动作取决于输入时钟&#xff08;或者使能&#xff09;信号的电平值。仅当锁存器处于使能状态时&#xff0c;输出才会随着…

HC32 IIC/I2C读写

IIC状态码 IIC 初始化 void iicInit(uint32_t speed) {stc_gpio_cfg_t stcGpioCfg;DDL_ZERO_STRUCT(stcGpioCfg);Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); //开启GPIO时钟门控stcGpioCfg.enDir GpioDirOut; ///< 端口方向配置…

【2023最新版】超详细NMAP安装保姆级教程,Nmap的介绍、功能并进行网络扫描,收藏这一篇就够了

简介 从诞生之初&#xff0c;Nmap就一直是网络发现和攻击界面测绘的首选工具。从主机发现和端口扫描&#xff0c;到操作系统检测和IDS规避/欺骗&#xff0c;Nmap是大大小小黑客行动的基本工具。 为了绘制网络拓扑图&#xff0c;Nmap的发送特制的数据包到目标主机&#xff0c;…

【Amazon】AI 代码生成器—Amazon CodeWhisperer初体验 | 开启开挂编程之旅

使用 AI 编码配套应用程序更快、更安全地构建应用程序 文章目录 1.1 Amazon CodeWhisperper简介1.2 Amazon CodeWhisperer 定价2.1 打开VS Code2.2 安装AWS ToolKit插件 一、前言 1.1 Amazon CodeWhisperper简介 1️⃣更快地完成更多工作 CodeWhisperer 经过数十亿行代码的训…

目标检测如何演变:从区域提议和 Haar 级联到零样本技术

目录 一、说明 二、目标检测路线图 2.1 路线图&#xff08;一般&#xff09; 2.2 路线图&#xff08;更传统的方法&#xff09; 2.3 路线图&#xff08;深度学习方法&#xff09; 2.4 对象检测指标的改进 三、传统检测方法 3.1 维奥拉-琼斯探测器 (2001) 3.2 HOG探测器…

为什么u盘在mac上显示不出来

插入U盘是个看似简单的操作&#xff0c;但有时候在Mac电脑上却出现了无法显示U盘的情况。这样的问题是非常让人头疼的&#xff0c;特别是当你急需使用U盘中的文件时。那么&#xff0c;究竟为什么U盘在Mac上会显示不出来呢&#xff1f;今天就让我们一起来深入了解一下这个问题&a…

编程新时代:Amazon CodeWhisperer 助您轻松驾驭代码世界

文章目录 一、什么是 Amazon CodeWhisperer&#xff1f;二、个人无限免费使用三、安装配置3.1 手把手教你在pycharm配置3.2 同理在VSCODE安装 三、Pycharm上测试3.1 根据注释写代码3.2 检查修复代码错误3.3 构建一个简单爬虫 四、 VSCODE上测试4.1 个性化体验4.2 系统兼容性4.3…

【再识C进阶3(下)】详细地认识字符分类函数,字符转换函数和内存函数

前言 &#x1f493;作者简介&#xff1a; 加油&#xff0c;旭杏&#xff0c;目前大二&#xff0c;正在学习C&#xff0c;数据结构等&#x1f440; &#x1f493;作者主页&#xff1a;加油&#xff0c;旭杏的主页&#x1f440; ⏩本文收录在&#xff1a;再识C进阶的专栏&#x1…

vuereact质检工具(eslint)安装使用总结

1、ESLint ESLint工具主要类似java中的checkStyle和findbugs&#xff0c;是检查代码样式和逻辑规范的工具。 1.1、ESLint安装流程 打开VSCode软件&#xff0c;打开扩展中心&#xff0c;下载ESLint插件 图1.1 点击后面的install按进行安装&#xff0c;如图1.2所示&#xff1…

黑马VUE3视频笔记

目录 一、使用create-vue创建项目 二、setup选项 三、reactive和ref函数 1.reactive() 2.ref() 三、computed 四、watch ​五、生命周期函数 六、父传子、子传父 父传子defineProps 子传父defineEmits 七、模板引用 ref defineExpose 八、跨层传递普通数据 prov…

SpringBoot 学习(二)配置

2. SpringBoot 配置 2.1 配置文件类型 配置文件用于修改 SpringBoot 的默认配置。 2.1.1 properties 文件 **properties ** 是属性文件后缀。 文件名&#xff1a;application.properties 只能保存键值对。 基础语法&#xff1a;keyvalue namewhy注入配置类 Component //…

百度SEO优化不稳定的原因分析(提升网站排名的稳定性)

百度SEO优化不稳定介绍蘑菇号-www.mooogu.cn SEO不稳定是指网站在搜索引擎中的排名不稳定&#xff0c;随着时间的推移会发生变化。这种情况可能会出现在网站页面结构、内容质量、外链质量等方面存在缺陷或不合理之处。因此&#xff0c;优化SEO非常重要&#xff0c;可以提高网站…

Cruise 的界面和模型文件路径介绍

文章目录 打开 Cruise自带模型所在路径自带模型分类Cruise 中的模型路径解析打开用户手册建模界面介绍打开模型 打开 Cruise 最新的几个 Cruise 软件都是集成到一个平台上的&#xff0c;名为 AVL Advanced Simulation Desktop。 自带模型所在路径 User 选项卡下的模型&#x…

Spring实现简单的Bean容器

1.BeanDefinition&#xff0c;用于定义 Bean 实例化信息&#xff0c;现在的实现是以一个 Object 存放对象 public class BeanDefinition {/*** bean对象*/private Object bean;/*** 存放 &#xff08;定义&#xff09;Bean 对象*/public BeanDefinition(Object bean) {this.bea…

关于TUM数据集

2、验证回环检测算法&#xff0c;需要有人工标记回环的数据集。然而人工标记回环是很不方便的&#xff0c;我们会考虑根据标准轨迹计算回环。即&#xff0c;如果轨迹中有两个帧的位姿非常相近&#xff0c;就认为它们是回环。请根据TUM数据集给出的标准轨迹&#xff0c;计算出一…

怎么选择伪原创工具?伪原创工具推荐

什么是伪原创工具&#xff1f;伪原创工具是一种可以将已有文本进行修改、改写或重新组合&#xff0c;生成新的文本内容的工具。 伪原创工具的作用 节省时间和精力&#xff1a;手工创作内容需要耗费大量时间和精力&#xff0c;而伪原创工具可以在短时间内生成大量内容&#xf…

嵌入式中如何用C语言操作sqlite3(07)

sqlite3编程接口非常多&#xff0c;对于初学者来说&#xff0c;我们暂时只需要掌握常用的几个函数&#xff0c;其他函数自然就知道如何使用了。 数据库 本篇假设数据库为my.db,有数据表student。 nonamescore4嵌入式开发爱好者89.0 创建表格语句如下&#xff1a; CREATE T…

C++中实现雪花算法来在秒级以及毫秒及时间内生成唯一id

1、雪花算法原理 雪花算法&#xff08;Snowflake Algorithm&#xff09;是一种用于生成唯一ID的算法&#xff0c;通常用于分布式系统中&#xff0c;以确保生成的ID在整个分布式系统中具有唯一性。它的名称来源于雪花的形状&#xff0c;因为生成的ID通常是64位的整数&#xff0…