嵌入式软件专题:设计模式一之FSM状态机模式使用

2023-11-12

本人已经从事嵌入式软件开发几年了,工作和学习中遇到不少项目,积累了一些代码编写和软件设计上的经验和技巧。借由这个专题进行梳理,和大家分享一下。

一、概念和设计思路

有限状态自动机(FSM), 是表示某个系统的有限个状态以及在外部事件的作用下在这些状态之间迁移和动作等行为的数学模型。具体概念就不细说了,找了几遍写的很好的文章放在引用这边,大家对状态机概念有兴趣可以去看看。
我主要想分享状态机模式的嵌入式应用,我认为使用状态机模式设计进行软件设计时,需要特别关注以下两点特性:
1、业务场景状态数明确,且不多,(状态数量保存在7个内较为理想)**
2、状态间跃迁指向明确,**

如下图的场景就适合使用状态机模式:
在这里插入图片描述

代码体现

enum stateList{ State1=1, State2=2, State3=3 };

void State1Event(){
	//。。。。
}
void State2Event(){
	//。。。。
}

void State3Event(){
	//。。。。
}

void main(){
	int nowState=State1;//初始状态,入口
	int loop=1;
	while(loop){
	 	switch(nowState){
		 	case State1:
				State1Event();
				nowState=State2;
				break;
		 	case State2:
				State2Event();
				nowState=State3;
				break;
		 	case State3:
				State3Event();
				if(判断条件){
					nowState=State1;
					break;
				}else{
					loop=0; //状态机出口
					break;
				}
			default:
				//重启系统
			break;
		}
	 }
}

二、具体适用场景

(一)业务场景下的软件框架设计

1、简单休眠产品的软件框架设计

在这里插入图片描述
注:不演示代码,请参考本文章:标题一、概念和设计思路。
此类业务场景很适合使用状态机模式进行软件框架设计,特别是如果因为本身业务场景不硬性rtos的机制,这就使得休眠场景可以容易抽离成一个系统状态进行。明确的区别出设备处于那种状态下运行,有利于简化软件结构,提高项目稳定性。

(二)单独功能模块设计

1、AT指令拨号联网过程:

在这里插入图片描述
实现代码:


```c
__task void net_task(void)
{
    OS_RESULT Result;
	u16 flag=1;
    //清除所有事件标志
	while(flag)
	{
			switch(gsm_state)
			{
				case GSM_INIT:
				{
					if(net_init() == 0)//查看iccid和pin,关闭回显,设置IPD头, 失败返回0 ,成功返回1
					{
						gsm_state = GSM_RESET;
					}
					else{
						gsm_state = GSM_CREG;
					}
				}
				break;
				case GSM_CREG:// AT握手 查看gsm网络状态,获取运营商, 失败返回0 ,成功返回1
				{
					if(net_reg() == 0)
					{
						gsm_state = GSM_RESET;
					}
					else{
						gsm_state = GSM_APN;
					}
				}
				break;
				case GSM_APN://设置PDP,APN, 失败返回0 ,成功返回1
				{			
					if(net_apn() == 0)
					{
						gsm_state = GSM_RESET;
					}
					else{
						gsm_state = GSM_OPEN;
					}
				}
				break;
				case GSM_OPEN:
				{
					if(net_socket(TCPServer, Port) == 0)//连接tcp服务器,失败返回0 ,成功返回1
					{
						gsm_state = GSM_RESET;
					}
					else
					{
						gsm_state = GSM_ONLINE;
					}
				}
				break;
				case GSM_ONLINE:
				{
					flag=0;//程序出口
				}
				break;
				case GSM_RESET:
				{
					gsm_reset_hard();
					gsm_state = GSM_INIT;
				}
				break;
				default:
					AT_DEBUG("状态异常\r\n");
					break;
			}
	}
}

根据当前状态执行相关功能同时明确跃迁条件,利用状态机模型可以有效增加软件模块的健壮性和可阅读性。

2、i2c通讯的功能Verilog代码实现:

在这里插入图片描述
这是项目中正点原子fpga实现I2C功能模块时的状态图,在此引用,加深大家对于状态机的理解。
对于单纯Verilog语言编程,缺乏C语言基本的指针和字符概念等特性,使用某个寄存器当作当前状态位是恰如其分的,因此在这种硬件描述言语的模块中使用状态机模式来设计则更加常见。同时也要注意过多的状态是否会导致系统繁杂,上图初看确实也有点眼花缭乱。

三、结尾

本次分享到这里结束,觉得对大家有用,可以点点赞,这是我更新的动力!!!

引用和参考文献:

https://zhuanlan.zhihu.com/p/623510269
https://blog.csdn.net/ronhu/article/details/124540166
https://blog.csdn.net/SjiaM/article/details/130615675
正点原子新起点之FPGA开发指南_V2.1

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌入式软件专题:设计模式一之FSM状态机模式使用 的相关文章

  • 本地缓存技术分享

    本地缓存 缓存分为本地缓存与分布式缓存 本地缓存为了保证线程安全问题 一般使用ConcurrentMap的方式保存在内存之中 而常见的分布式缓存则有Redis MongoDB等 一致性 本地缓存由于数据存储于内存之中 每个实例都有自己的副本
  • 深度学习&强化学习&进化计算 入门资源整理

    深度学习 强化学习 进化计算 入门资源整理 深度学习 在线课程 在线书籍 学习Python 强化学习 在线课程 在线书籍 更多资源 进化计算 后记 深度学习 在线课程 深度学习是机器学习领域的一个分支 想要入门深度学习 最好先对机器学习的一
  • 学会了,不会ps也能更换自己的证件照底色,制作自己的证件照

    证件照经常会由于背景色与要求不符而不能用 再去拍一组浪费时间和金钱 如何省时省力的把照片背景色修改成我们所需要的底色呢 说到修改照片背景色 首先想到大家常用的证件照 根据不同用处会要求 白 蓝 红 底色 在过去大家可能需要去图片社重新照 或
  • [631]一行js代码识别Selenium+Webdriver

    文章目录 一行js代码识别Selenium Webdriver 如何正确移除Selenium中的 window navigator webdriver 最新版 附一些网站检测selenium的示例 driver execute script
  • ESP32 SIM800L:发送带有传感器读数的文本消息(SMS警报)

    在这个项目中 我们将使用T Call ESP32 SIM800L模块创建一个SMS通知系统 当传感器读数高于或低于特定阈值时 该模块会发送SMS 在此示例中 我们将使用DS18B20温度传感器 并在温度高于28 C时发送短信 一旦温度降低到
  • uniapp使用scroll-view实现左右,上下滑动

    uniapp使用scroll view实现左右 上下滑动 阐述 我们在项目中往往都能遇到实现左右滑动跟上下滑动的需求 不需要安装better scroll uniapp 自带的scroll view 就可以实现了 实现左右滑动
  • 开源项目,源码

    GitHub 优秀的 Android 开源项目 转自 http blog csdn net shulianghan article details 18046021 主要介绍那些不错个性化的View 包括ListView ActionBar

随机推荐

  • java基础03:final

    说明 final是java的一个关键字 是最终的意思 final 表示 最后的 最终的 含义 变量一旦赋值后 不能被重新赋值 被 final 修饰的实例变量 就是已经实例化的对象 必须显式指定初始值 final 修饰符通常和 static
  • Flash钓鱼->CS上线(免杀过火绒、360等)

    先看结果 访问钓鱼页面 点击立即升级即把马儿下载下来了 这个马儿是rar压缩的 做成的rar解压自启动 所以是个exe的文件 然后这里为了像一点 把图标给改了 双击运行 查看效果 首先CS是没东西的 解压路径现在也是没东西的 这里我把解压路
  • C#值参数和引用参数

    C 值参数和引用参数 一 值参数 未用ref或out修饰符声明的参数为值参数 使用值参数 通过将实参的值复制到形参的方式 把数据传递到方法 方法被调用时 系统做如下操作 在栈中为形参分配空间 复制实参到形参 值参数的实参不一定是变量 它可以
  • 几年的Unity学习总结

    stream 其中类Stream为抽象类 由此有三个派生类 需要引入命名空间 using System IO MemoryStream 对内存进行读取与写入 BufferedStream 对缓冲器进行读取 写入 FileStream 对文件
  • access统计班级人数_使用ACCESS查询统计分数段人数

    不少人都知道使用电子表格 excel 进行分数段统计 使用access的人也可以用它设计查询进行分数段人数统计 这里假设你有一个access表 也可以是基表的查询 名叫tblScore 当然可以是中文名称 只不过代码内也要作相应修改 表内是
  • 大数据挖掘简介

    大数据挖掘涉及如下的课程 机器学习 统计学 人工智能 数据库等 但是更多的注重如下的特性 1 可扩展性 Scalability 大数据 2 算法和架构 3 自动的处理大数据 我们需要学习挖掘不同类型的数据 1 高维的数据 2 图数据 3 无
  • Vue技术 v-cloak指令(用于在 Vue 实例加载和编译之前隐藏元素)

    1 v cloak 指令的用法 v cloak 指令通常与 CSS 配合使用 用于在 Vue 实例加载和编译之前隐藏元素 通过给元素添加 v cloak 属性 然后在 CSS 中定义对应的样式 可以确保在 Vue 实例加载完成前 该元素的内
  • flex布局——flex-direction属性

    1 flex布局原理 1 flex是flexible Box的缩写 意为 弹性布局 用来为盒状模型提供最大的灵活性 任何一个容器都可以指定为flex布局 当我们为父盒子设为flex布局以后 子元素的float clear 和vertical
  • CentOS 7.9搭建Discuz 3.5论坛(LNMP)

    这里写目录标题 安装规格 安装nginx 安装依赖 编译配置Nginx 安装MySQL 设置MySQL Yum源并安装MySQL 查看MySQL初始密码并修改 安装并配置PHP 下载并解压Discuz 3 5 安装Discuz 安装规格 安
  • MMSegmentation笔记06:推理

    1 单张图像预测 author Seaton Time 2023 8 19 15 38 IDE PyCharm Summary 使用训练好的模型进行单张图像推理 import cv2 import matplotlib pyplot as
  • 对git rebase 和git merge的理解

    一 是什么 在使用 git 进行版本管理的项目中 当完成一个特性的开发并将其合并到 master 分支时 会有两种方式 git merge git rebase git rebase 与 git merge都有相同的作用 都是将一个分支的提
  • winhex常见问题:无法创建i:\TEMP\Win\WinHex 001.tmp,请确定文件夹存在且文件未被写保护

    点击菜单帮助 设置 初始化设置 恢复默认设置即可
  • 在虚拟环境下使用pip时默认使用系统环境的pip该怎么办

    入门小菜鸟 希望像做笔记记录自己学的东西 也希望能帮助到同样入门的人 更希望大佬们帮忙纠错啦 侵权立删 服务器的系统环境装的是python3 6 我建的虚拟环境装的是python3 7 用conda安装依赖包令人火大的各种报错 也许我跟co
  • 3-2.http 请求头Content-Type 为application/x-www-form-urlencoded

    本文测试 Content Type 为 multipart form data 的请求详情 前端页面模仿用户输入 用户名 密码 性别 爱好 城市等 可以看到请求头中 Content Type application x www form u
  • windows8.1 打不开网页 除ie外打不开网页 firefox chrome 打不开网页解决方法

    左下角 开始菜单右键 使用管理员 打开命令提示符 cmd 输入netsh winsock reset 就可以了 如果还不行 重启试下
  • 【docker】docker 安装配置 nginx+php+composer

    1 安装php7 安装docker就不赘述了 现在要在docker中安装php7 先拉镜像 docker pull php 7 1 fpm 这个镜像是把php和php fpm整合到一起 可以看做是php fpm 要配合nginx使用 先运行
  • 第七章 tcp发送(传输层)--基于Linux3.10

    由第五章可知 sock recvmsg和tcp sendmsg用于tcp层和应用层的接口 由第四章可知 tcp v4 rcv和tcp tarnsmit skb是传输层和网络层之间的接口 现在来看看tcp sendmsg是如何到tcp tar
  • Sqlmap的安装与简单使用

    一 概述 1 1 简介 sqlmap是一款开源的自动化渗透测试工具 可以扫描 发现并利用给定URL的SQL注入漏洞 检测动态页面中的get post参数 cookie http头 查看数据库数据 还可以访问文件系统 甚至能够执行操作系统命令
  • 【华为OD机试真题 Python语言】12、拼接URL

    文章目录 一 题目 题目描述 输入输出 样例1 样例2 样例3 二 思路参考 三 代码参考 作者 鲨鱼狼臧 个人博客首页 鲨鱼狼臧 专栏介绍 2023华为OD机试真题 使用Python进行解答 专栏每篇文章都包括真题 思路参考 代码分析 订
  • 嵌入式软件专题:设计模式一之FSM状态机模式使用

    本人已经从事嵌入式软件开发几年了 工作和学习中遇到不少项目 积累了一些代码编写和软件设计上的经验和技巧 借由这个专题进行梳理 和大家分享一下 目录 一 概念和设计思路 二 具体适用场景 一 业务场景下的软件框架设计 1 简单休眠产品的软件框