状态机的落到实处

自个儿是卓波,作者是一名嵌入式程序员,小编相对没悟出小编会在这里地跟我们说大话皮。

嵌入式框架Zorb Framework搭建进度

嵌入式框架Zorb Framework搭建生机勃勃:嵌入式情状搭建、调节和测验输出和创建刻间种类

嵌入式框架Zorb Framework搭建二:环形缓冲区的落到实处

嵌入式框架Zorb Framework搭建三:列表的贯彻

嵌入式框架Zorb Framework搭建四:状态机的兑现

嵌入式框架Zorb Framework搭建五:事件的完成

嵌入式框架Zorb Framework搭建六:停车计时器的贯彻

嵌入式框架Zorb Framework搭建七:职务的兑现

 

一、前言

  在此大器晚成篇中,大家将为Zorb Framework提供情状机作用。中型Mini型嵌入式程序说白了正是由各类状态机组成,由此调控了什么样构建状态机,开辟嵌入式应用程序能够说是毫不费劲。轻巧的状态机能够用Switch-Case完结,但复杂一点的情景机再继续利用Switch-Case的话,档次会变得相比较乱,不便利维护。由此大家为Zorb Framework提供了函数式状态机。

 

二、状态机设计

  我们先来看看要达成的状态机提供如何效益:

  起头要提供的效用如下:

  1、能够设置初叶状态

  2、可以拓展处境调换

  3、能够打开时域信号调治

  4、最CANON够在步向和离开状态的时候能够做一些自定义的事情

  5、最佳能(CANON卡塔尔够有子状态机

  因而,初阶设计的数据结构如下: 

 1 /* 状态机结构 */
 2 struct _Fsm
 3 {
 4     uint8_t Level;                  /* 嵌套层数,根状态机层数为1,子状态机层数自增 */
 5                                     /* 注:严禁递归嵌套和环形嵌套 */
 6     List *ChildList;                /* 子状态机列表 */
 7     Fsm *Owner;                     /* 父状态机 */
 8     IFsmState OwnerTriggerState;    /* 当父状态机为设定状态时,才触发当前状态机 */
 9                                     /* 若不设定,则当执行完父状态机,立即运行子状态机 */
10     IFsmState CurrentState;         /* 当前状态 */
11     bool IsRunning;                 /* 是否正在运行(默认关) */
12     
13     /* 设置初始状态 */
14     void (*SetInitialState)(Fsm * const pFsm, IFsmState initialState);
15     
16     /* 运行当前状态机 */
17     bool (*Run)(Fsm * const pFsm);
18     
19     /* 运行当前状态机和子状态机 */
20     bool (*RunAll)(Fsm * const pFsm);
21     
22     /* 停止当前状态机 */
23     bool (*Stop)(Fsm * const pFsm);
24     
25     /* 停止当前状态机和子状态机 */
26     bool (*StopAll)(Fsm * const pFsm);
27     
28     /* 释放当前状态机 */
29     bool (*Dispose)(Fsm * const pFsm);
30     
31     /* 释放当前状态机和子状态机 */
32     bool (*DisposeAll)(Fsm * const pFsm);
33     
34     /* 添加子状态机 */
35     bool (*AddChild)(Fsm * const pFsm, Fsm * const pChildFsm);
36     
37     /* 移除子状态机(不释放空间) */
38     bool (*RemoveChild)(Fsm * const pFsm, Fsm * const pChildFsm);
39     
40     /* 调度状态机 */
41     bool (*Dispatch)(Fsm * const pFsm, FsmSignal const signal);
42     
43     /* 状态转移 */
44     void (*Transfer)(Fsm * const pFsm, IFsmState nextState);
45     
46     /* 状态转移(触发转出和转入事件) */
47     void (*TransferWithEvent)(Fsm * const pFsm, IFsmState nextState);
48 };

  关于复信号,Zorb Framework做了以下定义:

1 /* 状态机信号0-31保留,用户信号在32以后定义 */
2 enum {
3     FSM_NULL_SIG = 0,
4     FSM_ENTER_SIG,
5     FSM_EXIT_SIG,
6     FSM_USER_SIG_START = 32
7     /* 用户信号请在用户文件定义,不允许在此定义 */
8 };

  个中,0-31为框架功率信号,客户频限信号在32随后定义。

  状态机已经安插好了,具体达成请看附属类小零器件代码或在文末的github地址拉框架源码。

 

三、状态机结果测量检验

  轻易的测验代码如下:

  1 /**
  2   *****************************************************************************
  3   * @file    app_fsm.c
  4   * @author  Zorb
  5   * @version V1.0.0
  6   * @date    2018-06-28
  7   * @brief   状态机测试的实现
  8   *****************************************************************************
  9   * @history
 10   *
 11   * 1. Date:2018-06-28
 12   *    Author:Zorb
 13   *    Modification:建立文件
 14   *
 15   *****************************************************************************
 16   */
 17 
 18 #include "app_fsm.h"
 19 #include "zf_includes.h"
 20 
 21 /* 定义用户信号 */
 22 enum Signal
 23 {
 24     SAY_HELLO = FSM_USER_SIG_START
 25 };
 26 
 27 Fsm *pFsm;        /* 父状态机 */
 28 Fsm *pFsmSon;     /* 子状态机 */
 29 
 30 /* 父状态机状态1 */
 31 static void State1(Fsm * const pFsm, FsmSignal const fsmSignal);
 32 /* 父状态机状态2 */
 33 static void State2(Fsm * const pFsm, FsmSignal const fsmSignal);
 34 
 35 /******************************************************************************
 36  * 描述  :父状态机状态1
 37  * 参数  :-pFsm       当前状态机
 38  *         -fsmSignal  当前调度信号
 39  * 返回  :无
 40 ******************************************************************************/
 41 static void State1(Fsm * const pFsm, FsmSignal const fsmSignal)
 42 {
 43     switch(fsmSignal)
 44     {
 45         case FSM_ENTER_SIG:
 46             ZF_DEBUG(LOG_D, "enter state1rn");
 47             break;
 48         
 49         case FSM_EXIT_SIG:
 50             ZF_DEBUG(LOG_D, "exit state1rnrn");
 51             break;
 52         
 53         case SAY_HELLO:
 54             ZF_DEBUG(LOG_D, "state1 say hello, and want to be state2rn");
 55             /* 切换到状态2 */
 56             pFsm->TransferWithEvent(pFsm, State2);
 57             break;
 58     }
 59 }
 60 
 61 /******************************************************************************
 62  * 描述  :父状态机状态2
 63  * 参数  :-pFsm       当前状态机
 64  *         -fsmSignal  当前调度信号
 65  * 返回  :无
 66 ******************************************************************************/
 67 static void State2(Fsm * const pFsm, FsmSignal const fsmSignal)
 68 {
 69     switch(fsmSignal)
 70     {
 71         case FSM_ENTER_SIG:
 72             ZF_DEBUG(LOG_D, "enter state2rn");
 73             break;
 74         
 75         case FSM_EXIT_SIG:
 76             ZF_DEBUG(LOG_D, "exit state2rnrn");
 77             break;
 78         
 79         case SAY_HELLO:
 80             ZF_DEBUG(LOG_D, "state2 say hello, and want to be state1rn");
 81             /* 切换到状态1 */
 82             pFsm->TransferWithEvent(pFsm, State1);
 83             break;
 84     }
 85 }
 86 
 87 /******************************************************************************
 88  * 描述  :子状态机状态
 89  * 参数  :-pFsm       当前状态机
 90  *         -fsmSignal  当前调度信号
 91  * 返回  :无
 92 ******************************************************************************/
 93 static void SonState(Fsm * const pFsm, FsmSignal const fsmSignal)
 94 {
 95     switch(fsmSignal)
 96     {
 97         case SAY_HELLO:
 98             ZF_DEBUG(LOG_D, "son say hello only in state2rn");
 99             break;
100     }
101 }
102 
103 /******************************************************************************
104  * 描述  :任务初始化
105  * 参数  :无
106  * 返回  :无
107 ******************************************************************************/
108 void App_Fsm_init(void)
109 {
110     /* 创建父状态机,并设初始状态 */
111     Fsm_create(&pFsm);
112     pFsm->SetInitialState(pFsm, State1);
113     
114     /* 创建子状态机,并设初始状态 */
115     Fsm_create(&pFsmSon);
116     pFsmSon->SetInitialState(pFsmSon, SonState);
117     
118     /* 设置子状态机仅在父状态State2触发 */
119     pFsmSon->OwnerTriggerState = State2;
120     
121     /* 把子状态机添加到父状态机 */
122     pFsm->AddChild(pFsm, pFsmSon);
123     
124     /* 运行状态机 */
125     pFsm->RunAll(pFsm);
126 }
127 
128 /******************************************************************************
129  * 描述  :任务程序
130  * 参数  :无
131  * 返回  :无
132 ******************************************************************************/
133 void App_Fsm_process(void)
134 {
135     ZF_DELAY_MS(1000);
136     /* 每1000ms调度状态机,发送SAY_HELLO信号 */
137     pFsm->Dispatch(pFsm, SAY_HELLO);
138 }
139 
140 /******************************** END OF FILE ********************************/

  结果:

state1 say hello, and want to be state2
exit state1

enter state2
son say hello only in state2
state2 say hello, and want to be state1
exit state2

enter state1
state1 say hello, and want to be state2
exit state1

enter state2
son say hello only in state2
state2 say hello, and want to be state1
exit state2

enter state1
state1 say hello, and want to be state2
exit state1

省略...

 

四、最后

  本篇为Zorb Framework提供了情况机作用,复杂的境况调换关系被分解成了三个个动静函数,然后在状态函数中独有必要管理本状态现身的境况,忽地以为世界变得轻松超多。后边再配上将要为框架加多的风浪功用,会让状态机的意义发挥到十二万分。

 

  Zorb Framework github:

  版权全体,转发请打赏哟

 

设若你喜欢本人的稿子,能够经过Wechat扫一扫给本人打赏哟

图片 1

本文由星彩网app下载发布于计算机编程,转载请注明出处:状态机的落到实处

TAG标签: 星彩网app下载
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。