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

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

一、概念和设计思路

有限状态自动机(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

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

水厂小白@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值