有限状态机——The finite state machine

2024-06-06 00:48

本文主要是介绍有限状态机——The finite state machine,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

依据状态之间是否有包含关系,分以下两种
(1)常规状态机。状态机中的所有状态是不相交的、互斥的。
(2)层次状态机。状态机中的状态之间要么是互斥的,要么是真包含的,可以用树性结构来描述这些状态集,包含其它状态的状态称为枝节点,不包含其它状态的状态称为叶节点,为方便单树描述,总是设计一个状态包含所有的状态节点,称为根节点。状态机的状态只能停留在叶节点,而不能停留在枝节点,每个枝节点需要指定一个子节点为它的默认子节点,以便状态机进入枝节点的时候能够停留到叶节点。

一般都用switch/case if/else方式实现。在少量状态(3个及其以下)的时候,不需要引入专门的状态机模块。

常规状态机模块实现涉及到的结构由上而下为:
顶层结构是状态机:当前状态id,缺省操作,状态表,
状态表:状态数组
状态结构:状态id,状态名,进入操作,退出操作,缺省操作,状态事件表(数组)
状态事件结构:操作,事件,下一状态的id
***************************************************************************************
从代码易读及美观角度来说,建议用switch/case来实现。
从经验来看,在一些稍大的程序设计中一般都会有状态机的实现,特别是在分层实现,协议栈实现,编解码方面。
下面通过一个简单的例子来看下。这个例子是zigbee精简协议栈实现中的【这里只讲APS层的有限状态机,这是开放源代码的,对于该协议总体上是分层来实现的,每一次层都有状态机来进行实际的数据业务处理】。
(1)定义各状态
typedef enum _APS_STATE_ENUM
{
  APS_STATE_IDLE,
  APS_STATE_COMMAND_START,
  APS_STATE_GENERIC_TX_WAIT,
  APS_STATE_NWK_PASSTHRU_WAIT,
  APS_STATE_INDIRECT_GETDST,
  APS_STATE_INDIRECT_TX,
#ifdef LRWPAN_COORDINATOR
  APS_STATE_INJECT_INDIRECT,
#endif
  APS_STATE_ACK_SEND_START,
  APS_STATE_INDIRECT_TX_WAIT,
  APS_STATE_INJECT_LOOPBACK,
  APS_STATE_INDIRECT_LOOPBACK
 } APS_STATE_ENUM;
(2)设计有限状态机函数
void apsFSM(void)
{
apsFSM_start://状态机入口
switch (apsState) //全局变量,指示当前状态
 {
  case APS_STATE_IDLE:
  if (aps_pib.flags.bits.ackSendPending)
   {
    apsState = APS_STATE_ACK_SEND_START;//状态转换
    goto apsFSM_start;
   }
   break;
 case APS_STATE_ACK_SEND_START:
   if (phyTxLocked())
   {
    break;
   }
   //send an ACK
   //lock the TX buffer
   phyGrabTxLock();
   //we are now ready
   apsFormatAck();
   phy_pib.currentTxFlen = 0;  //set frame length to zero, build from scratch
   apsTxData(TRUE);
   //data sent, release the RX buffer, will let RX FSM resume
   aps_pib.flags.bits.ackSendPending = 0;
   apsState = APS_STATE_GENERIC_TX_WAIT;
break;
case APS_STATE_GENERIC_TX_WAIT:
   if (!apsTXIdle())
   {
    break;
   }
   //TX is finished, copy status
   a_aps_service.status = apsTxFSM_status;
   //release the TX buffer lock before exiting.
   phyReleaseTxLock();
   apsState = APS_STATE_IDLE;
   if (aps_pib.flags.bits.indirectPending)
   {
    //have used this state to wait for finishing sending an
    //ACK back to the source of an indirect transmit. Now
    //finish resolving the indirect
    goto apsFSM_start;
   }
   break;
case APS_STATE_NWK_PASSTHRU_WAIT:
   //for split-phase passthrus
   if (nwkBusy())
   {
    break;
   }
   a_aps_service.status = a_nwk_service.status;
   apsState = APS_STATE_IDLE;
   break;
case APS_STATE_INJECT_LOOPBACK:
   //wait for RX to become idle
   if (apsRxState != APS_RXSTATE_IDLE)
   {
    break;
   }
   //inject packet into RX FSM
   apsInjectPacket(FALSE);
   aps_pib.flags.bits.IsUsrBufferFree = 1;
   apsState = APS_STATE_IDLE;
   goto apsFSM_start;
 default:
  break;
 }
}
(3)大致结构:状态机入口,状态转换,状态机退出
从这个函数实现,我们可以简单了解有限状态机的实现过程。当程序的实现有多个状态的时候,也就是要根据不同的状态做不同的事情的时候,可以考虑把某个操作过程拆分为几个步骤【很多时候这是必须的】,对应状态机操作的几个不同状态。多数情况下,这些状态是多个操作可以共用的。一般的状态机函数都会提供一个状态退出操作,每个状态操作可以根据条件来判断是要退出,还是要转换进行下一个状态的。
状态机是程序设计时的一种思想,尤如设计模式,只有在恰当的时候用来才回体现出其价值。

这篇关于有限状态机——The finite state machine的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1034644

相关文章

状态模式state

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/state 在一个对象的内部状态变化时改变其行为, 使其看上去就像改变了自身所属的类一样。 在状态模式中,player.getState()获取的是player的当前状态,通常是一个实现了状态接口的对象。 onPlay()是状态模式中定义的一个方法,不同状态下(例如“正在播放”、“暂停

正规式与有限自动机例题

答案:D 知识点: 正规式 正规集 举例 ab 字符串ab构成的集合 {ab} a|b 字符串a,b构成的集合 {a,b} a^* 由0或者多个a构成的字符串集合 {空,a,aa,aaa,aaaa····} (a|b)^* 所有字符a和b构成的串的集合 {空,a,b,ab,aab,aba,aaab····} a(a|b)^* 以a为首字符的a,b字符串的集

ZOJ 3324 Machine(线段树区间合并)

这道题网上很多代码是错误的,由于后台数据水,他们可以AC。 比如这组数据 10 3 p 0 9 r 0 5 r 6 9 输出应该是 0 1 1 所以有的人直接记录该区间是否被覆盖过的方法是错误的 正确方法应该是记录这段区间的最小高度(就是最接近初始位置的高度),和最小高度对应的最长左区间和右区间 开一个sum记录这段区间最小高度的块数,min_v 记录该区间最小高度 cover

STM32F4按键状态机--单击、双击、长按

STM32F4按键状态机--单击、双击、长按 一、状态机的三要素二、使用状态机原因2.1资源占用方面2.2 执行效率方面:2.3 按键抖动方面: 三、状态机实现3.1 状态机分析3.1 程序实现 百度解析的状态机概念如下 状态机由状态寄存器和组合逻辑电路构成,能够根据控制信号按照预先设定的状态进行状态转移,是协调相关信号动作、完成特定操作的控制中心。有限状态机简写为FSM(

Apache-Flink深度解析-State

来源:https://dwz.cn/xrMCqbk5 Flink系列精华文章合集入门篇: Flink入门Flink DataSet&DataSteam APIFlink集群部署Flink重启策略Flink分布式缓存Flink重启策略Flink中的TimeFlink中的窗口Flink的时间戳和水印Flink广播变量Flink-Kafka-connetorFlink-Table&SQLFlink

Flink使用Broadcast State实现流处理配置实时更新

大数据技术与架构 点击右侧关注,大数据开发领域最强公众号! 暴走大数据 点击右侧关注,暴走大数据! 本文作者时延军发表在http://shiyanjun.cn,如果你也在使用Broadcast State,那么可以参考一下。 Broadcast State是Flink支持的一种Operator State。使用Broadcast State,可以在Flink程序的一个Stream中输入数

Spring 状态机

文章目录 使用 Spring 状态机构建订单处理系统什么是 Spring 状态机?示例场景:订单处理系统步骤 1: 添加依赖步骤 2: 定义状态和事件步骤 3: 配置状态机步骤 4: 使用状态机步骤 5: 测试状态机Spring 状态机原理详细说明核心概念实现机制 使用 Spring 状态机构建订单处理系统 在构建复杂的业务流程时,状态机是一种强大的工具。它帮助我们定义状态、

【C++ 前缀和 状态机dp】2826. 将三个组排序

本文涉及的基础知识点 C++算法:前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 C++动态规划 LeetCode2826. 将三个组排序 给你一个整数数组 nums 。nums 的每个元素是 1,2 或 3。在每次操作中,你可以删除 nums 中的一个元素。返回使 nums 成为 非递减 顺序所需操作数的 最小值。 示例 1: 输入:nums = [2,1,3,2,1] 输

HDU1150/POJ1325_Machine Schedule(二分图/最小点覆盖=最大匹配)

解题报告 http://blog.csdn.net/juncoder/article/details/38147135 题目传送门(POJ) 题目传送门(HDU) 题意: A机器有n个模式,B机器有m个模式,每个作业可以在任何机器的特定模式下工作,转换模式需要耗时,求最小耗时 思路: 把AB两机器的模式当成二分图顶点,模式之间的连线就是某个作业可以在该两个模式下工作,就转换成求最小

Machine Learning Week2

Matlab for MAC 下载 address:ClickHere Matlab for MAC 学习地址:ClickHere Multivariate Linear Regression 当有更多信息提供来预测时用multivariate linear regression : n: 有多少已知信息(feature) x^(i): 第i 个training example的已知信息