有限状态机(FSM)的设计与实现

有限状态机设计(Verilog HDL) 由于两者模型的差别,不难看出,Mealy型状态机当输入改变时输出也会立即改变,不依赖时钟,而Moore型状态机输入状态改变时,需要经过时钟同步后输出才会改变,即Moore型状态机比Mealy型状态机输出要多一个时钟周期。图中可以看出,Mealy型状态机相较于Moore型状态机,其输出逻辑多了一个输入端,即上述定义所说的Mealy型状态机输出由当前状态(现态CS)和当前输入决定。1.先画出状态转移图,比较丑,但大概是这样,简单起见,不考虑找零,不投硬币也不算输入。2.Verilog描述。 阅读详情

http://www.cnblogs.com/chencheng/archive/2012/06/25/2562660.html

有限状态机(FSM)是表示有限个状态及在这些状态之间的转移和动作等行为的数学模型,在计算机领域有着广泛的应用。通常FSM包含几个要素:状态的管理、状态的监控、状态的触发、状态触发后引发的动作。本文主要阐述一下状态机的几种设计方法。

1:switch case/if else设计方法

复制代码
curEvent = getEvent();
curState = getCurState();
switch(curState)
{
    case state1:
    {
        switch(curEvent )
        {
             TODO...
             setCurState();
             break; 
        }
        break;
    }
    ...
}
复制代码

这种设计方法最简单,通过一大堆判断来处理,适合小规模的状态切换流程,但如果规模扩大难以扩展和维护。

2:基于表结构的状态机设计方法:建立相应的状态表和动作查询表,根据状态表、事件、动作表定位相应的动作处理函数,执行完成后再进行状态的切换。

一个通用的状态机处理模块的设计如下:

复制代码
/*状态表注册*/
void
FSM_Regist(FSM_T* pFsm,STATE_TABLE_S* pStateTable) { pFsm->FsmTable = pStateTable; return; } /*状态迁移*/ void FSM_MoveState(FSM_T* pFsm,int state) { pFsm->curState = state; return; }
/*事件处理*/
void FSM_EventHandle(FSM_T* pFsm,int event) { ACT_TABLE_T* pActTable = NULL; ActFun eventActFun = NULL; /*获取当前状态动作表*/ pActTable = FSM_getActTable(pFsm); /*获取当前动作函数*/ for(int i=0;i<MAX_ACT_NUM;i++) { if(event == pActTable[i].event) { eventActFun = pActTable[i].eventActFun; break; } } /*动作执行*/ if(eventActFun) { eventActFun(pFsm); } }
复制代码

假设我们的状态图如下:


相应的状态机设置如下:

复制代码
/*状态1的动作表*/
ACT_TABLE_T state1ActTable[] = {
    {EVENT1,state1Event1Fun},
    {EVENT3,state1Event3Fun},
};
/*状态2的动作表*/
ACT_TABLE_T state2ActTable[] = {
    {EVENT2,state2Event2Fun},
};
/*状态表*/
STATE_TABLE_T FsmTable[] = {
    {STATE1,state1ActTable},
    {STATE2,state2ActTable},
};

int main(int argc, _TCHAR* argv[])
{
    FSM_T fsm;
    /*状态表注册*/
    FSM_Regist(&fsm,FsmTable);
    FSM_MoveState(&fsm,STATE1);
    FSM_EventHandle(&fsm,EVENT1);
    FSM_EventHandle(&fsm,EVENT2);
    return 0;
}
/*客户端提供的状态处理函数*/
void state1Event1Fun(void* pFsm) { FSM_MoveState((FSM_T*)pFsm,STATE2);
return; } void state1Event3Fun(void* pFsm) { FSM_MoveState((FSM_T*)pFsm,STATE3);
return; } void state2Event2Fun(void* pFsm) { FSM_MoveState((FSM_T*)pFsm,STATE3);
return; }
复制代码

通过设计一个通用的基于表结构的状态机模块,针对不同的状态图,我们只需要根据状态图得到其状态表结构,然后通过FSM_Regist注册,就可以方便的使用了状态机的功能了。这种机制便于我们添加新的状态流程,并且可以很好的进行分层状态机的设计。

分层状态机的设计:
对于状态较多的状态机,通常的设计会维护一个庞大的二维矩阵,所有状态耦合在一起,这往往导致维护困难,由于可能存在许多公共的特性,也会导致许多状态具有相同的处理函数。针对这些问题我们可以通过设计分层状态机来解决,主要的思想就是根据不同的功能模块设计出多个状态机,各个状态机分布在不同的层次上。上层状态机调用下层状态机时,上层状态机入栈,下层状态机变为当前处理状态机。通常我们使用堆栈来保存当前状态机的上层状态机信息。

下图描述一个分层状态机设计实现:


如上图所示,假设L1为上层状态机,L1状态机在L1_STATE2中可以通过L1L2_EVENT1事件触发进入L2状态机,L2状态机在L2_STATE2中通过L1L2_EVENT2事件触发返回L1状态机,L1和L2各自维护自己的状态表。

数据结构:

复制代码
struct FSM_S
{
    int curState;                        //当前状态机状态
    int curFsmTableSize;                 //当前状态机查询表大小
    STATE_TABLE_T* curFsmTable;          //当前状态机查询表
    FSM_STACK_T stack[MAX_FSM_STACK_DEP];//状态机堆栈
    int curStackTop;                     //栈顶
    FSM_REGIST_T registFsm[MAX_FSM_NUM]; //注册状态机
    int registFsmNum;                    //注册状态机个数
};
复制代码

1:通过堆栈数据结构维护上层状态机信息。

2:保存所有可以注册状态机信息。

3:记录当前运行状态机信息。

主要接口:

复制代码
void FSM_Init(FSM_T* pFsm);
void FSM_Regist(FSM_T* pFsm,STATE_TABLE_S* pStateTable,int FsmId,int curFsmTableSize);
void FSM_Begin(FSM_T* pFsm,int FsmId);
void FSM_MoveState(FSM_T* pFsm,int state);
void FSM_EventHandle(FSM_T* pFsm,int event);
void FSM_Push(FSM_T* pFsm);
void FSM_Pop(FSM_T* pFsm);
复制代码

1:FSM_Regist 对所有的状态机信息进行注册

复制代码
void FSM_Regist(FSM_T* pFsm,STATE_TABLE_S* pStateTable,int FsmId, int curFsmTableSize)
{
    pFsm->registFsm[pFsm->registFsmNum].fsmId = FsmId;
    pFsm->registFsm[pFsm->registFsmNum].FsmTable = pStateTable;
    pFsm->registFsm[pFsm->registFsmNum].fsmTableSize = curFsmTableSize;

    pFsm->registFsmNum++;
    return;
}
复制代码

2:FSM_Begin 用于开始一个新的状态机流程,切换状态表信息。

复制代码
void FSM_Begin(FSM_T* pFsm,int FsmId)
{
    for(int i=0;i<pFsm->registFsmNum;i++)
    {
        if(FsmId == pFsm->registFsm[i].fsmId)
        {
            pFsm->curFsmTable = pFsm->registFsm[i].FsmTable;
            pFsm->curFsmTableSize = pFsm->registFsm[i].fsmTableSize;
            break;
        }
    }
    return;
}
复制代码

3:FSM_Push/FSM_Pop 用于状态机切换的出入堆栈操作。

复制代码
void FSM_Push(FSM_T* pFsm)
{
    if(pFsm->curStackTop < MAX_FSM_STACK_DEP)
    {
        pFsm->curStackTop++;
        pFsm->stack[pFsm->curStackTop].state     = pFsm->curState;
        pFsm->stack[pFsm->curStackTop].pFsmTable = pFsm->curFsmTable;
        pFsm->stack[pFsm->curStackTop].fsmTableSize = pFsm->curFsmTableSize;
    }

    return;
}

void FSM_Pop(FSM_T* pFsm)
{
    if(pFsm->curStackTop > -1)
    {
        pFsm->curState   = pFsm->stack[pFsm->curStackTop].state;
        pFsm->curFsmTable = pFsm->stack[pFsm->curStackTop].pFsmTable;
        pFsm->curFsmTableSize = pFsm->stack[pFsm->curStackTop].fsmTableSize;
        pFsm->curStackTop--;
    }

    return;
}
复制代码

 接口的使用:

复制代码
/*L1 状态机定义*/
ACT_TABLE_T L1state1ActTable[] = {
    {L1_EVENT1,L1state1_Event1Fun},
    {L1_EVENT3,L1state1_Event3Fun},
};
ACT_TABLE_T L1state2ActTable[] = {
    {L1_EVENT2,L1state2_Event2Fun},
    {L1_L2_EVENT1,L1state2_L1L2EventFun},
};
STATE_TABLE_T L1FsmTable[] = {
    {L1_STATE1,sizeof(L1state1ActTable)/sizeof(ACT_TABLE_T),L1state1ActTable},
    {L1_STATE2,sizeof(L1state2ActTable)/sizeof(ACT_TABLE_T),L1state2ActTable},
};
/*L2 状态机定义*/
ACT_TABLE_T L2state1ActTable[] = {
    {L2_EVENT1,L2state1_L2Event1Fun},
};
ACT_TABLE_T L2state2ActTable[] = {
    {L1_L2_EVENT2,L2state2_L1L2EvenFun},
};
STATE_TABLE_T L2FsmTable[] = {
    {L2_STATE1,sizeof(L2state1ActTable)/sizeof(ACT_TABLE_T),L2state1ActTable},
    {L2_STATE2,sizeof(L2state2ActTable)/sizeof(ACT_TABLE_T),L2state2ActTable},
};

int main(int argc, _TCHAR* argv[])
{
    FSM_T pFsm;
FSM_Init(
&pFsm); /*状态机注册*/ FSM_Regist(&pFsm,L1FsmTable,FSM_L1,sizeof(L1FsmTable)/sizeof(STATE_TABLE_T)); FSM_Regist(&pFsm,L2FsmTable,FSM_L2,sizeof(L2FsmTable)/sizeof(STATE_TABLE_T)); /*开始L1状态机*/ FSM_Begin(&pFsm,FSM_L1); FSM_MoveState(&pFsm,L1_STATE1); FSM_EventHandle(&pFsm,L1_EVENT1); /*push 状态机*/ FSM_EventHandle(&pFsm,L1_L2_EVENT1); /*L2状态机处理*/ FSM_EventHandle(&pFsm,L2_EVENT1); /*pop 状态机*/ FSM_EventHandle(&pFsm,L1_L2_EVENT2); /*L1状态机处理*/ FSM_EventHandle(&pFsm,L1_EVENT2); return 0; }
复制代码

1:首先通过FSM_Regist注册所有的状态机。

2:FSM_EventHandle(&pFsm,L1_L2_EVENT1)中的动作处理函数中进行压栈操作同时进入L2状态机。

复制代码
void L1state2_L1L2EventFun(void* pFsm)
{
    FSM_Push((FSM_T*)pFsm);
    FSM_Begin((FSM_T*)pFsm,FSM_L2);
    FSM_MoveState((FSM_T*)pFsm,L2_STATE1);

    return;
}
复制代码

3:FSM_EventHandle(&pFsm,L1_L2_EVENT2)中的动作处理函数中进行出栈操作返回到L1状态机。

void L2state2_L1L2EvenFun(void* pFsm)
{
    FSM_Pop((FSM_T*)pFsm);

    return;
}

 结论:

通过分层状态机的设计,各个功能实体维护自身的强相关的一套状态机,可以有效的减小状态机的复杂度,通过构建公共流程状态机,可以减小规模。综上所述:在针对规模较大、流程复杂的状态机设计,我们考虑使用分层的设计方法。


【算法】有限状态机FSM 使用C++实现一套简单的状态机模型——实例:https://fangliang.blog.youkuaiyun.com/article/details/44042287 使用C++实现一套简单的状态机模型——原理解析:https://fangliang.blog.youkuaiyun.com/article/details/44120809 阅读详情

相关推荐

订单有限状态机架构设计

有限状态机 有限状态机(Finite-state machine, FSM),是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。主要用来是描述对象在它的生命周期内所经历的状态序列,以及如何响应来自外界的各种事件。 状态机可归纳为4个要素,即现态、条件、动作、新态。其中“现态”和“条件”是因,“动作”和“次态”是果。 **现态:**是指当前所处的状态。 **事件:**又称为“条件”。当一个事件发生,将会触发一个动作,或者执行一次状态的迁移。 **动作:**条件满足后执行的动作。动作执

KobeHoo的博客 3227

FSM(有限状态机)

本文介绍FSM(有限状态机),以及如何引用、解决问题案例

SjiaM的博客 1万+

C语言实现有限状态机

1. 什么是有限状态机 有限状态机在百度百科上的解释为: 有限状态自动机(FSM “finite state machine” 或者FSA “finite state automaton” )是为研究有限内存的计算过程和某些语言类而抽象出的一种计算模型。有限状态自动机拥有有限数量的状态,每个状态可以迁移到零个或多个状态,输入字串决定执行哪个状态的迁移。有限状态自动机可以表示为一个有向图。 2. 有...

遇见你是我最美丽的意外 1万+

Verilog有限状态机设计

过程1(除全灭)一共有18/2=9个状态,过程2亦有9个状态,再加上2个全灭状态(这两个状态并不相同,因为其下一状态不是同一个状态),一共20个状态。2、控制18个led灯从两边往中间逐个亮后全灭,再从中间往两边逐个亮后全灭,循环执行上述过程。3、3个always,分别实现当前状态的更新cs、下一个状态的更新以及输出的更新。四、“101”序列检测器的Verilog描述。1、控制4个led灯从左往右顺序循坏点亮。2、定义状态存储变量cs,ns。六、有限状态机的设计要点。二、 有限状态机的分类。

m0_74036728的博客 972

【Unity 笔记】有限状态机 FSM

【Unity】 有限状态机 FSM 游戏引擎:Unity 版本:2019.4.6f1 【2017版本以上均可】 编译平台:Visual Studio 2019   一、什么是FSM   FSM 全名 [Finite State Machine]。中文名 [有限状态机],又称 [有限状态自动机],简称 [状态机]。 1.1 了解Animator组件   Unity为我们提供了Animator组件,便利开发者更加自主的实现更多动画的控制方式。   快捷链接:Unity Animator官方文档介绍 2.2 有

Mr.River的博客 1851

【行为决策模块项目实战】有限状态机FSM设计方法及代码实现(附C++代码)

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录系列文章目录前言一、步骤1:思考清楚系统所有的状态和转移条件,画出状态转移图示例(fast_planning)二、设计有限状态机FSM的枚举状态与变量三、设计状态机的初始化函数四、设计状态转移函数五、设计检查状态机FSM正在执行的状态的函数(定时调用,用于debug)六、【重要】设计执行状态机FSM的定时器回调函数总结 前言 认知有限,望大家多多包涵,有什么问题也希望能够与大家多交流,共同成

qq_35635374的博客 1768

第6章 游戏AI决策系统的核心——有限状态机(FSM)设计与实现

摘要 本章介绍了有限状态机(FSM)在游戏AI中的应用,重点分析了经典游戏《吃豆人》中红幽灵的FSM实现。FSM通过定义离散状态(如追逐、散射、恐惧和被吃)及其转换条件,有效模拟了游戏角色的智能行为。示例代码展示了完整的红幽灵AI系统,包括状态管理、行为设置、路径计算和动画控制等核心组件。该实现体现了商业游戏中FSM的设计思路,如状态计时器、目标位置计算和视觉反馈更新等关键技术点。

小宝哥Code的专栏 762

有限状态机FSM设计方法及代码实现(附C++代码)

本文先对简单的有限状态机设计方法做个简单的介绍,具体内容后续再更,其他模块可以参考去我其他文章提示:以下是本篇文章正文内容本文举例是以fast_planning开源工程为例子抽象出来的这是较为简单的有限状态机的基本实现框架,具体的根据自己的业务设计状态和状态的实现,或者对状态图进行扩充。

qq_35635374的博客 294

FPGA 14 按键滤波模块设计实验(有限状态机【FSM】实现)

FPGA学习 11 按键消抖实验 key_filter.v文件 //定义按键函数端口 module key_filter( Clk , Rst_n , key_in , key_flag, //检测按键成功信号 key_state //实时的信号 ); input Clk ; input Rst_n ; input key_in ; output reg key_flag ; output reg key_state ; //定义状态机 localparam

lj1986817902的博客 1314

数字系统设计中的有限状态机教程:FSM深入解析与实现

有限状态机(FSM)是一种计算模型,它能通过一系列预定义的状态和规则来响应事件。状态机在各种系统和应用中广泛使用,它们能够模拟决策过程,并且在理解计算机程序的工作原理方面起到了关键作用。FSM的概念主要围绕三个核心要素:状态、事件和动作。状态代表了系统的不同配置或模式;事件则是触发状态转换的信号;动作是在特定事件发生时所执行的操作。有限状态机是由有限个状态、状态之间的转移规则、输入事件和输出动作组成的模型。FSM在逻辑电路设计、软件开发、通信协议等领域都有着不可或缺的作用。

weixin_42356162的博客 1486

SpringBoot与Flowable整合:构建高效审批工作流的实战指南

本文是一份SpringBoot与Flowable整合构建高效审批工作流的实战指南。通过一个经典的二级审批场景,详细介绍了从项目搭建、BPMN流程设计、核心服务编写到RESTful API构建的完整步骤。文章深入探讨了如何利用Flowable工作流引擎实现审批流程的自动化驱动与灵活管理,并分享了变量管理、监听器、异步执行等进阶技巧与常见避坑指南,帮助开发者快速构建健壮、可维护的企业级审批系统。

qsc9012345的博客 520

有限状态机(FSM)的设计与实现(一)

有限状态机(FSM)是表示有限个状态及在这些状态之间的转移和动作等行为的数学模型,在计算机领域有着广泛的应用。通常FSM包含几个要素:状态的管理、状态的监控、状态的触发、状态触发后引发的动作。本文主要阐述一下状态机的几种设计方法。 1:switch case/if else设计方法 curEvent = getEvent(); curState = getCurState(); swi

xdgs_2005的专栏 465

【论文精读】Latent Diffusion

Latent Diffusion

weixin_44934783的博客 4478

有限状态机(FSM)的设计与实现

有限状态机(FSM)是表示有限个状态及在这些状态之间的转移和动作等行为的数学模型,在计算机领域有着广泛的应用。通常FSM包含几个要素:状态的管理、状态的监控、状态的触发、状态触发后引发的动作。本文主要阐述一下状态机的几种设计方法。 1:switch case/if else设计方法 curEvent = getEvent(); curState = getCurState(); swi...

weixin_30869099的博客 256

基于SSM的足浴管理系统(源码+开题)

研究内容: 本研究的内容主要包括以下几个方面:首先,我们需要对现有的足浴管理系统进行深入的研究和分析,了解其优缺点;最后,我们需要对新设计的系统进行评估和优化,以满足用户的需求和提升系统的使用体验。因此,开发一种基于SSM的足浴管理系统,能够有效地解决这些问题,提高足浴服务的质量和效率。研究目的: 本研究的主要目的是设计和实现一个功能完善、操作简便、用户体验良好的基于SSM的足浴管理系统。通过对系统的研究和设计,我们希望能够为足浴服务行业提供一个高效、便捷的工具,从而推动足浴服务行业的发展。

林科程序设计 1688

电磁波函数复数表示法:为什么物理学家偏爱e^(ikz)而非cos(kr-wt)?

本文深入解析了电磁波函数复数表示法(如e^(ikz))相较于传统余弦形式的巨大优势。通过欧拉公式,复数形式将复杂的三角运算转化为简洁的指数运算,在微分、积分、线性叠加及处理相位时展现出极高的计算效率,是物理学家和工程师分析波动现象的核心工具。

weixin_29094539的博客 499

有限状态机(FSM)的设计与实现(1)

转自:http://www.cnblogs.com/chencheng/archive/2012/06/25/2562660.html 有限状态机(FSM)是表示有限个状态及在这些状态之间的转移和动作等行为的数学模型,在计算机领域有着广泛的应用。通常FSM包含几个要素:状态的管理、状态的监控、状态的触发、状态触发后引发的动作。本文主要阐述一下状态机的几种设计方法。 1:switch cas

lxgwm2008的专栏 1524

2025最新OSM中国矢量数据保姆级下载指南(附百度网盘链接)

本文提供2025年OSM中国矢量数据的保姆级下载与使用指南。详细介绍了通过Geofabrik镜像站、QGIS插件及第三方平台获取数据的多种途径,重点解析了Shapefile格式数据的结构、WGS84坐标系特性,并指导进行格式转换与基础GIS应用,帮助用户高效合规地获取并利用这份开放地理数据资源。

weixin_29228781的博客 884

有限状态机(FSM)的设计与实现(二)

转自:http://www.cnblogs.com/chencheng/archive/2012/06/28/2564336.html 分层状态机的设计: 对于状态较多的状态机,通常的设计会维护一个庞大的二维矩阵,所有状态耦合在一起,这往往导致维护困难,由于可能存在许多公共的特性,也会导致许多状态具有相同的处理函数。针对这些问题我们可以通过设计分层状态机来解决,主要的思想就是根

折戟 1062

【01】总目录——软件设计师50讲通关地图|从零基础到工程师职称

本文是《软件设计师·50讲通关|从零基础到工程师职称》专栏的01篇总目录,系统梳理了50篇博文的完整架构与核心逻辑。专栏覆盖软考软件设计师(中级)全部考点,分为导学规划、基础知识、设计模式、下午题专项、算法实战、冲刺模拟、收官进阶七大模块,既兼顾上午题75道单选题的理论攻坚,也聚焦下午题案例分析的解题能力提升。每篇博文均包含考点精讲、真题解析、实战技巧与速记方法,配套可运行代码、解题模板及备考资源。无论你是零基础转行、在校学生还是在职程序员,都能通过这份学习地图明确进度、精准定位薄弱环节,高效搭建知识体系

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 1281

uni-app - 刘海屏(Iphone X)底部横杠(——)白色区域块(安全距离处更改颜色)解决方案

场景:因为要做无tabbar页面,所以在配置文件中取消底部导航栏。取消后,iPhoneX(刘海屏)底部就出现如下图所示白色安全区域问题:这个问题,是因为uni-app默认会为iPhoneX(刘海屏)留出安全距离,这个安全距离的背景色就是白色。所以,如果你将页面颜色设置为其他颜色,就会与默认白色冲突。有2个不同的解决方案(原生占位),虽然原理是一样,但使用的场景不同,请根据您的需求来采纳。

🏆 前端领域优质创作者 1万+

掌握数字系统设计精髓:有限状态机(FSM)从理论到实战

verilog复制下载localparam [4:0] IDLE = 5'b00001, // 状态0:初始/空闲HAS_5 = 5'b00010, // 状态1:已投5元HAS_10 = 5'b00100, // 状态2:已投10元 (可购买)HAS_15 = 5'b01000, // 状态3:已投15元 (需找零)DISPENSE= 5'b10000, // 状态4:出货状态// 状态5:退币状态 (这里用了6种状态,5位独热足够)

Zihan2558的博客 1159

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

上一篇: 基于有限状态机的交互组件设计与实现
下一篇: Web 研发模式演变
起风啰
博客等级 码龄16年 30粉丝 4原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值