0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

使用函数指针的方法实现状态机

GReq_mcu168 来源:玩转单片机 作者:玩转单片机 2020-10-19 09:36 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

之前写过一篇状态机的实用文章,很多朋友说有几个地方有点难度不易理解,今天给大家换种简单写法,使用函数指针的方法实现状态机。

状态机简介

有限状态机FSM是有限个状态及在这些状态之间的转移和动作等行为的数学模型,是一种逻辑单元内部的高效编程方法,可以根据不同状态或者消息类型进行相应的处理逻辑,使得程序逻辑清晰易懂。

函数指针实现FSM

使用函数指针实现FSM可以分为3个步骤

建立相应的状态表和动作查询表

根据状态表、事件、动作表定位相应的动作处理函数

执行完成后再进行状态的切换

代码实现步骤

定义状态数据的枚举类型

typedefenum{ state_1=1, state_2, state_3, state_4 }State;

定义事件的枚举类型

typedefenum{ event_1=1, event_2, event_3, event_4, event_5 }EventID;

定义状态表的数据类型

typedefstruct { intevent;//事件 intCurState;//当前状态 void(*eventActFun)();//函数指针 intNextState;//下一个状态 }StateTable;

定义处理函数及建立状态表

voidf121() { printf("thisisf121 "); } voidf221() { printf("thisisf221 "); } voidf321() { printf("thisisf321 "); } voidf122() { printf("thisisf122 "); } StateTablefTable[]= { //{到来的事件,当前的状态,将要要执行的函数,下一个状态} {event_1,state_1,f121,event_2}, {event_2,state_2,f221,event_3}, {event_3,state_3,f321,event_4}, {event_4,state_4,f122,event_1}, //addyourcodehere };

状态机类型,及状态机接口函数

/*状态机类型*/ typedefstruct{ intcurState;//当前状态 StateTable*stateTable;//状态表 intsize;//表的项数 }fsmType; /*状态机注册,给它一个状态表*/ voidfsmRegist(fsmType*pFsm,StateTable*pTable) { pFsm->stateTable=pTable; } /*状态迁移*/ voidfsmStateTransfer(fsmType*pFsm,intstate) { pFsm->curState=state; } /*事件处理*/ voidfsmEventHandle(fsmType*pFsm,intevent) { StateTable*pActTable=pFsm->stateTable; void(*eventActFun)()=NULL;//函数指针初始化为空 intNextState; intCurState=pFsm->curState; intmaxNum=pFsm->size; intflag=0;//标识是否满足条件 /*获取当前动作函数*/ for(inti=0;i

附代码

代码直接复制过去就行啦,本想打包的,太麻烦了。

测试程序

//编译器:http://www.dooccn.com/cpp/ //来源:技术让梦想更伟大 //作者:李肖遥 #include typedefenum{ state_1=1, state_2, state_3, state_4 }State; typedefenum{ event_1=1, event_2, event_3, event_4, event_5 }EventID; typedefstruct{ intevent;//事件 intCurState;//当前状态 void(*eventActFun)();//函数指针 intNextState;//下一个状态 }StateTable; voidf121() { printf("thisisf121 "); } voidf221() { printf("thisisf221 "); } voidf321() { printf("thisisf321 "); } voidf122() { printf("thisisf122 "); } StateTablefTable[]= { //{到来的事件,当前的状态,将要要执行的函数,下一个状态} {event_1,state_1,f121,event_2}, {event_2,state_2,f221,event_3}, {event_3,state_3,f321,event_4}, {event_4,state_4,f122,event_1}, //addyourcodehere }; /*状态机类型*/ typedefstruct{ intcurState;//当前状态 StateTable*stateTable;//状态表 intsize;//表的项数 }fsmType; /*状态机注册,给它一个状态表*/ voidfsmRegist(fsmType*pFsm,StateTable*pTable) { pFsm->stateTable=pTable; } /*状态迁移*/ voidfsmStateTransfer(fsmType*pFsm,intstate) { pFsm->curState=state; } /*事件处理*/ voidfsmEventHandle(fsmType*pFsm,intevent) { StateTable*pActTable=pFsm->stateTable; void(*eventActFun)()=NULL;//函数指针初始化为空 intNextState; intCurState=pFsm->curState; intmaxNum=pFsm->size; intflag=0;//标识是否满足条件 /*获取当前动作函数*/ for(inti=0;i

编译结果

总结

使用函数指针实现的FSM的过程还是比较费时费力的,但是这一切相对一大堆的if/else、switch/case来说都是值得的,当你的程序规模变得越来越大的时候,基于这种表结构的状态机,维护程序起来会清晰很多。

原文标题:【编程之美】函数指针方法实现简单状态机(附代码)

文章出处:【微信公众号:玩转单片机】欢迎添加关注!文章转载请注明出处。

责任编辑:haq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 编程
    +关注

    关注

    90

    文章

    3707

    浏览量

    96759
  • 函数
    +关注

    关注

    3

    文章

    4406

    浏览量

    66831
  • 指针
    +关注

    关注

    1

    文章

    484

    浏览量

    71673

原文标题:【编程之美】函数指针方法实现简单状态机(附代码)

文章出处:【微信号:mcu168,微信公众号:硬件攻城狮】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    睿远研究院丨IO-Link规范解读(十一):ISDU状态机与EVENT事件

    上篇我们介绍了ISDU的典型编码格式和应用案例,本篇我们就来详细介绍下,ISDU的状态机,并把EVENT事件的逻辑,给大家好好解析下。 1主站ISDU状态机 如上图所示,ISDU的状态机的核心
    的头像 发表于 11-29 18:28 2651次阅读
    睿远研究院丨IO-Link规范解读(十一):ISDU<b class='flag-5'>状态机</b>与EVENT事件

    什么是状态机

    的switch—case语句里要有400个case,这样的程序还有法儿写么?! 同样的功能改动,如果用g_stFSM这个结构体来实现状态机的话,函数fsm_active()只需要
    发表于 11-27 08:15

    嵌入式开发为何经常用到状态机架构

    ,这样CPU就闲不下来了。 这种处理方法的实质就是在程序等待事件的过程中间隔性地插入一些有意义的工作,好让CPU不是一直无谓地等待。 二、逻辑完备性 逻辑完备性是状态机编程最大的优点。 不知道大家
    发表于 11-25 07:08

    睿远研究院丨IO-Link规范解读(六):主从站状态机解析

    前言 书接上文,今天我们就来好好聊聊主从站的DL-Mode状态机,还请各位童鞋前排坐好! 1主站状态机解析 主站的DL-Mode状态机有5个大状态,也是我们很熟悉的 建立通信、开始、预
    的头像 发表于 10-28 17:34 5752次阅读
    睿远研究院丨IO-Link规范解读(六):主从站<b class='flag-5'>状态机</b>解析

    通过 BOD 或 nReset 重置时,GPIO 是否处于高实现状态

    正如标题所说,我正在使用 ML51 来控制外部 MOS 组件,GPIO 类型在复位条件下非常重要。GPIO 是否处于高实现状态
    发表于 08-25 07:04

    JTAG标准的状态机实现

    JTAG作为一项国际标准测试协议(IEEE1149.1兼容),主要用于芯片内部测试和调试。目前的主流芯片均支持JTAG协议,如DSP、FPGA、ARM、部分单片等。标准的JTAG接口是20Pin,但JTAG实际使用的只有4根信号线,再配合电源、地。
    的头像 发表于 08-21 15:12 2053次阅读
    JTAG标准的<b class='flag-5'>状态机</b><b class='flag-5'>实现</b>

    请问如何在FX10上使用GPIF III状态机 *.h 文件?

    LVCMOS 2 位 SlaveFIFO GPIF III 状态机的演示中有一个 cy_gpif_header_lvcmos.h 文件。 我想知道如何使用.h文件,只需放入.h文件放入 FX10 项目? 您有它的用户指南文档吗?
    发表于 07-16 08:17

    NVMe高速传输之摆脱XDMA设计之八:PCIe初始化状态机设计

    PCIe配置初始化状态机实现PCIe设备枚举和配置空间初始化过程,在完成链路训练后,使用DFS(深度优先搜索)算法枚举PCIe总线上的设备,完成PCIe总线域的地址分配和设备的初始化。PCIe配置
    发表于 07-05 22:00

    有可能在 FX3 GPIF2 中创建两个独立的状态机吗?

    我想,如果我想通过 FX3 GPIF2 创建两个独立的传输流接口,我需要在 GPIF2 设计器中创建两个独立的状态机,我是否有可能在 GPIF2 设计器中创建两个独立的状态机
    发表于 05-20 06:14

    cypress3014视频格式改变的话,GPIF状态机需不需要重新配置?

    你好,请问视频格式改变的话,GPIF状态机需不需要重新配置
    发表于 05-14 07:28

    [Actor]在程序框图编程时,如何操作消息和方法对应的VI

    actor应用的关键: 当在程序框图编程时,核心是针对“消息”vi 进行操作,并不操作消息对应的方法vi(具体要实现的功能)。 调用的消息vi时,后台自动调用对应方法vi。 相当于在队列状态机
    发表于 05-13 18:10

    求助,关于srammaster.cydsn中状态机的问题求解

    晚上好。 我目前正在学习 GPIF II。 查看..EZ-USB FX3 SDK1.3firmwaregpif_examplescyfxsrammastersrammaster.cydsn中的状态机,有状态START和START1。 这意味着什么?
    发表于 05-12 06:20

    NVME控制器之队列管理模块

    时,表示队列为满;当Head指针等于Tail指针时,表示队列为空。该模块中的状态机用来实现门铃寄存器信息更新的流程控制工作。队列管理状态机
    发表于 05-03 20:19

    函数指针的六个常见应用场景

    函数指针在嵌入式开发中有着广泛的应用,它让代码更加灵活,减少冗余,提高可扩展性。很多时候,我们需要根据不同的情况动态调用不同的函数,而函数指针
    的头像 发表于 04-07 11:58 1120次阅读
    <b class='flag-5'>函数</b><b class='flag-5'>指针</b>的六个常见应用场景

    Simulink中的状态机建模方法 Simulink数据可视化与分析功能

    1. Simulink中的状态机建模方法 1.1 理解状态机的基本概念 在开始建模之前,了解状态机的基本概念是必要的。状态机由以下几个部分组
    的头像 发表于 12-12 09:27 4273次阅读