新闻  |   论坛  |   博客  |   在线研讨会
【技术笔记】重拾那些嵌入式编程技巧---状态机
电子禅石 | 2020-04-24 17:39:13    阅读:289   发布文章
状态机,全称有限状态机(英语:Finite-state machine, FSM),是一种常用的数学模型。在软件编程领域中,它是一种引人骄傲的重炮利器,是一种思想,堪称艺术。

本文将讲解状态机的从入门到“精通”的那些事。有限状态机讲述了有限个状态、以及它们之间相互的动作以及转移的过程最早接触状态机是在数字电路中的触发器章节,书中清晰的使用了状态图来描述触发器工作机理。

1.png


图1 D触发器的状态图

后来在EDA课程中的FPGA设计中,终于有机会将状态机应用于实际电路编程中。在那一刻,状态机概念就像一个烙印刻在心里,无法抹去。

             switch-case   

相信大多数初学者和我一样,第一次编写状态机是使用switch-case结构来实现的。忆当年,我在C51单片机编程中第一次引入“状态机”,实现功能竟是判断按键是否按下。按键的动作可以分为如下几个状态:等待被按下S_BTN_WAIT_PRESSED、安全被按下S_BTN_PRESSED、等待松开S_BTN_WAIT_RELEASED。其中等待被按下和安全被按下过程之间应该进行按键的消抖操作。

2.png

图2 D按键检测状态图

按照上图所示,使用switch-case结构的状态机如下:

3.png


switch-case结构实现的状态机,可谓“简单粗暴”。写出来的代码放在一块,一眼就可以看出整个状态机包含了多少个状态,而且每个case就是一个状态。整体容易区分,简单。那“粗暴”从何说起?想象一下,如果这个状态机有10个甚至更多的状态,每个case里面的if结构层数又比较多的时候,总体代码篇幅就会显得很长,臃肿庞大。代码那么“粗”,感觉屏幕都要“暴”炸了。另外也会引入这样的问题,如果case过多,switch的出口就会大大增加(break就会增加),对于阅读代码时就会极其不便。所以switch-case可以应付简单的状态机。那么对于如何解决上述问题呢?

这时候一位因敲代码成仙的仙人指明了方向——函数指针

             函数指针   

使用函数指针实现状态机的时候,每一个函数都可以认为一个单独的状态,输入参数可以作为状态转移的触发动作。

现在展示一下初级版本的函数指针状态机,编写一个空调的代码。空调状态机中包含了三个状态:空调关机、空调送风、空调制冷。每个状态下需要辨识的动作是两个按键:开关键按下、送风/制冷按键按下。他们的转移关系图如下:

4.png


表1 空调状态转移表


按照上表描述的状态转移过程,空调状态机代码如下:



可以看出,函数指针实现的状态机,就显得“苗条”一点。每个状态通过一个函数实现,函数的输入参数用来传递事件,函数的返回值又作为下一个空调的状态。这种方式的状态机具有更好的可扩展型,比如空调要卖到南方的话,要再增加一个空调除湿模式。这时候,只需要增加一个函数,其他函数保留不动即可。相比switch-case下,函数层次更为分明,功能高度内聚,更加符合“高内聚、低耦合”的软件设计原则。

             总结   

以上内容简单讲述了switch-case和函数指针实现的状态机以及各自的优缺点。更加复杂的状态机版本可以使用状态转移表来实现。一个二维或者多维的数组存放着所有状态转移的可能性,通过查表的方法即可知道转移的下一个状态。例如:

 newState = switchTab[EVT0][EVT1][oldState]; 

上式表示为:在状态oldState下,如果同时发生了事件为EVT0和EVT1时,那么下一个状态就是newState。这种方式省去了在状态中对事件进行if的逻辑判断,更加适合用于事件有限并且事件类型可用整数表示的情形。


*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
属于自己的技术积累分享,成为嵌入式系统研发高手。
推荐文章
最近访客