程序小白
认证:优质创作者
所在专题目录 查看专题
【第二章】HSM层次式状态机理论(进阶版)
【第三章】有限状态机(FSM)之炸弹项目(实战1)
【第四章】有限状态机(FSM)之炸弹项目(实战2)
【第五章】有限状态机(FSM)之炸弹项目(实战3)
【第六章】层次式状态机HSM = 有限状态机FSM + 面向对象
【第七章】如何创建基于HSM状态机的应用
作者动态 更多
小小调度器——开局default,优雅总藏于细节之中
04-02 09:23
小小调度器——调度器核心的纯C实现
04-01 14:09
小小调度器——原来C代码还能这么写,原作者没少挨打吧!
03-27 15:42
解析由系统库引发的hardfault血案(RT-Thread+ESP32)
2023-07-17 16:04
TINA瞬时现象仿真分析——运放缓冲器振铃
2023-02-28 11:38

【第六章】层次式状态机HSM = 有限状态机FSM + 面向对象

      状态机发展至今,其实传统的FSM应用场合其实并不多了,他虽然可以解决确定性的问题,但是他无法解决软件重复的问题,层次式状态机HSM就是为解决这个问题而提出来的,层次式状态机HSM = 有限状态机FSM(状态机技术) + 面向对象(复用技术),这就是我理解的层次式状态机的本质。

      层次式状态机相比于有限状态机,在状态转换方面复杂了很多,因为他有了子状态和父状态的概念,曾经的FSM,其实也可以看做是一种特殊的层次式状态机,也就是他们拥有共同的父状态,这种情况下,从一个状态转换到另一个状态的步骤是固定的,但是一旦两人不再同一个状态层次,问题就变得复杂了很多。

      当然也带来了很多的好处,比如当前的子状态机中,并不需要对每一个需要响应的事件进行动作的处理,假如很多拥有相同的父状态的子状态,都需要对同一个事件作出相同的响应,这时候只需要在父状态中统一处理一次就可以了,也就是所有的子状态都继承了父状态的事件处理,这种在状态机里面会有一个新的名字,行为继承。

      层次式状态机的实现相对来讲是比较复杂的,所有的事件触发,状态转换都和自身的层相关,以状态转换为例,他需要实现以下转换,整个转换的过程无疑是很复杂的,但是没必要深入把他搞懂,了解就可以了。如下:

      层次式事件处理器被设计出来就是为了解决这些麻烦的转换算法,假如你不需要再造一个处理器(轮子),可以忽略这一部分算法,直接应用就可以,也就是核心是如何使用层次式状态机来设计我们的程序,要达到这一目的,你就必要掌握给定一个状态模型,任何一个触发导致的事件动作或者状态转换的先后顺序及执行的流程(路径),掌握了这些,你基本上就掌握了层次式状态机的核心规则,基于这个核心规则,你可以设计自己的层次式状态机,并用于实际的项目中。

      掌握一项技能最好的方式就是通过实战,其实针对状态机运行规则这块,官方提供了一个可以玩的例程,不需要嵌入式硬件的支持,我们就可以实战,通过这个例程基本上囊括了一个层次式状态机所有可能出现的转换的情况,掌握了他,你也就掌握了层次式状态机的运行规则,废话不多说,直接上例程,先看一下,用于验证层次式状态执行的这个例程的状态图,如下:

      看着还是比较复杂的,接下来,我们直接让这个应用程序跑起来,看看初始化完成以后他停在哪,执行了哪些操作。

     

      执行过程:首先完成TopInit顶层初始化,然后触发了一个TRAN转换,这个转换的最终目标是S2,但是S2并不是一个最终的子状态,S2要向最终的子状态过渡,首先要进入S2状态,首先要执行S1-ENTRY,然后执行S2-ENTRY,然后发现执行S2-INIT,INIT触发状态转换,执行S21-ENTRY ,S211-ENTRY,完成最终转换。

      这里要注意几点:

      第一、并不是所有的状态都要有INIT事件处理,但是如果该状态不是最终子状态,则需要一个INIT。

      第二、并不是的INIT在触发转换以后都会执行,只有当触发转换是某个超状态时,并且完成了到达该超状态的进入动作以后,停留在了该超状态,因为超状态不能作为最终的根,所以需要触发INIT来完成到最终的根的转换。

      第三、系统的状态永远都是停留在最终的某个子状态,例如上面的S211,当有信号发送给当前状态时,可能并没有对应的事件相应的处理,这时候他会递归到其上一层也就是Q_SUPER的状态,查找是否有相应的处理响应,如果没有就一直往上找,直到找到为止,如果到了HSMTOP层还是没有,整个信号也就被忽略掉了。

      第四、两个状态要进行转换,首先要找到两个状态的最小的共同超状态(有点类似于数学里面那个最小公因数)。然后从源状态一路退出至最小共同超状态,然后再沿着最小共同超状态这条路,一路进入到目标状态,执行完这个过程状态转换完成。

      继续我们的应用例程,当前状态处于S211,这个时候,我们按下键盘的F键,触发f事件,来分析一下系统将会作出什么样的反应,根据我们上述总结的几点:

      1. 当前处于S211的状态,查找其状态或者其超状态是否有对应的信号响应,根据状态图可以看到,其响应为S2状态,响应动作为状态转换,目标状态位s11。

      2.开始执行源状态S211---->S11目标状态的转换,先查找其最小共同超状态,我们看状态图一眼就能看出来,但是程序上算法查找还是比较复杂的,这里看图说话,最小共同超状态为S状态。

      3.从源状态一路退出至S,s211-EXIT;s21-EXIT;s2-EXIT;

       4.从S一路进入至S11,s1-ENTRY;s11-ENTRY;

真实的执行结果如下:

      带有内置参数的事件处理,两次执行相同的事件可能会返回不同的执行路径,现象如下:

      S11内部处理的代码如下:

      

超状态S1的相关内部代码如下:

这个可以尝试自己分析一下,根据代码和状态图,分析一下为什么会有两种不同的输出。

      除此之外还有很多的事件信号可以被触发,例如下面:

      感兴趣可以自己下载源码跑起来,自己操作和分析,需要源码的话也可以留言,留下邮箱,我打包发给大家。看到这里HSM的变换流程就基本差不多了。

声明:本内容为作者独立观点,不代表电子星球立场。未经允许不得转载。授权事宜与稿件投诉,请联系:editor@netbroad.com
觉得内容不错的朋友,别忘了一键三连哦!
赞 6
收藏 7
关注 117
成为作者 赚取收益
全部留言
0/200
成为第一个和作者交流的人吧