状态机编程

有限状态机的工作原理:发生事件(event)后,根据当前状态(cur_state) ,决定执行的动作(action),并设置下一个状态号(nxt_state)。

 

 
 

状态机可以用两种方法实现:竖着写(在状态中判断事件)和横着写(在事件中判断状态)。这两种实现在本质上是完全等效的,但在实际操作中,效果却截然不同。

  1. 竖着写(在状态中判断事件)C代码片段:

        cur_state = nxt_state;     

  1. switch(cur_state) //在当前状态中判断事件  
  2. {              
  3.     case s0: //在s0状态     
  4.         if(e0_event) //如果发生e0事件,那么就执行a0动作,并保持状态不变;  
  5.         {     
  6.     //执行a0动作;                 
  7.     //nxt_state = s0;  //因为状态号是自身,所以可以删除此句,以提高运行速度。  
  8.         }   
  9.         else if(e1_event) //如果发生e1事件,那么就执行a1动作,并将状态转移到s1态;  
  10.         {     
  11.             //执行a1动作;  
  12.             nxt_state = s1;  
  13.         }             
  14.         else if(e2_event) //如果发生e2事件,那么就执行a2动作,并将状态转移到s2态;  
  15.         {    
  16.             //执行a2动作;  
  17.             nxt_state = s2;  
  18.         }  
  19.         else  
  20.         {  
  21.             break;      
  22.         }     
  23.   
  24.     case s1: //在s1状态  
  25.         if(e2_event) //如果发生e2事件,那么就执行a2动作,并将状态转移到s2态;   
  26.         {                  
  27.             //执行a2动作;  
  28.          nxt_state = s2;  
  29.         }             
  30.         else  
  31.         {  
  32. break;  
  33.         }  
  34.   
  35.     case s2: //在s2状态  
  36.         if(e0_event)  //如果发生e0事件,那么就执行a0动作,并将状态转移到s0态;  
  37.         {  
  38.             //执行a0动作;                 
  39.             nxt_state = s0;  
  40.         }  
  41. }

 

  1. 横着写(在事件中判断状态)C代码片段:
  1. //e0事件发生时,执行的函数  
  2. void e0_event_function(int * nxt_state)  
  3. {     
  4.     int cur_state;     
  5.     cur_state = *nxt_state;     
  6.     switch(cur_state)  
  7.     {         
  8.         case s0: //观察表1,在e0事件发生时,s1处为空     
  9.         case s2: //执行a0动作;             
  10.         *nxt_state = s0;  
  11.     }  
  12. }  
  13.   
  14. //e1事件发生时,执行的函数  
  15. void e1_event_function(int * nxt_state)  
  16. {     
  17.     int cur_state;     
  18.     cur_state = *nxt_state;     
  19.     switch(cur_state)  
  20.     {         
  21.         case s0: //观察表1,在e1事件发生时,s1和s2处为空             
  22.             //执行a1动作;             
  23.             *nxt_state = s1;  
  24.     }  
  25. }  
  26.   
  27. //e2事件发生时,执行的函数  
  28. void e2_event_function(int * nxt_state)  
  29. {     
  30.     int cur_state;     
  31.     cur_state = *nxt_state;     
  32.     switch(cur_state)  
  33.     {         
  34.         case s0: //观察表1,在e2事件发生时,s2处为空         
  35.         case s1:             
  36.             //执行a2动作;             
  37.             *nxt_state = s2;   
  38.     }  
  39. }  

上面横竖两种写法的代码片段,实现的功能完全相同,但是,横着写的效果明显好于竖着写的效果。理由如下:

1、竖着写隐含了优先级排序(其实各个事件是同优先级的),排在前面的事件判断将毫无疑问地优先于排在后面的事件判断。这种if/else if写法上的限制将破坏事件间原有的关系。而横着写不存在此问题。

2、由于处在每个状态时的事件数目不一致,而且事件发生的时间是随机的,无法预先确定,导致竖着写沦落为顺序查询方式,结构上的缺陷使得大量时间被浪费。对于横着写,在某个时间点,状态是唯一确定的,在事件里查找状态只要使用switch语句,能一步定位到相应的状态,延迟时间可以预先准确估算。而且在事件发生时,调用事件函数,在函数里查找唯一确定的状态,并根据其执行动作和状态转移的思路清晰简洁,效率高,富有美感。

竖着写的方法也不是完全不能使用,在一些小项目里,逻辑不太复杂,功能精简,同时为了节约内存耗费,竖着写的方法也不失为一种合适的选择。

 

参考:https://blog.csdn.net/V__KING__/article/details/71740492

  • 6
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
单片机状态机编程思想是一种常用的软件设计方法,用于处理复杂的系统控制逻辑。它将系统的行为分解为一系列离散的状态,并定义了状态之间的转换条件和动作。以下是单片机状态机编程思想的基本概念和实现方式: 1. 状态(State):表示系统在某一时刻的工作状态,可以是一个具体的功能或操作。例如,一个电梯系统可以有"停止"、"上升"和"下降"等状态。 2. 事件(Event):触发状态转换的外部或内部事件,可以是传感器输入、定时器溢出等。例如,电梯系统中的事件可以是"按下上升按钮"、"到达某一楼层"等。 3. 状态转换(Transition):定义了从一个状态到另一个状态的条件和动作。条件可以是事件的发生、某些输入信号的状态等。动作可以是改变输出、执行某些操作等。例如,当电梯处于"停止"状态时,如果接收到"按下上升按钮"事件,则转换到"上升"状态,并执行相应的动作。 4. 状态机(StateMachine):由一组状态、事件和状态转换组成的模型,描述了系统的行为。通过不断地检测事件和执行状态转换,状态机可以实现系统的控制逻辑。 在单片机中实现状态机编程思想可以采用以下步骤: 1. 定义状态:根据系统需求,确定系统的各个状态,并为每个状态分配一个唯一的标识符。 2. 定义事件:根据系统需求,确定可能触发状态转换的事件,并为每个事件分配一个唯一的标识符。 3. 定义状态转换:为每个状态定义可能的状态转换条件和动作。根据事件和当前状态,确定下一个状态和执行的动作。 4. 实现状态机:在单片机程序中,使用条件语句或查表法等方式实现状态机。通过不断地检测事件和执行状态转换,实现系统的控制逻辑。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值