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

    文章

    3723

    浏览量

    97437
  • 函数
    +关注

    关注

    3

    文章

    4422

    浏览量

    67847
  • 指针
    +关注

    关注

    1

    文章

    484

    浏览量

    71960

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

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

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

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    指针函数详解

    = a + b; return(p); } 这是一个简单的指针函数的例子,运行结果如下,本文代码在VScode平台运行,使用方法《使用VScode调试C语言》。 不过我有个疑问,使用
    发表于 01-23 06:02

    函数指针介绍

    函数指针类型 定义函数指针类型,必须使用typedef,方法就是,在“定义函数
    发表于 01-21 08:11

    函数指针与回调函数解读

    函数指针是指向函数指针变量。通过函数指针C语言可以实现
    发表于 01-19 07:34

    函数指针指针函数的区别

    = fun(a);   注意指针函数函数指针表示方法的不同,千万不要混淆。最简单的辨别方式就是看函数
    发表于 12-12 06:34

    函数指针的概念

    函数指针是指向函数指针变量。 通常我们说的指针变量是指向一个整型、字符型或数组等变量,而函数
    发表于 12-11 08:10

    回调函数例子的应用

    步骤,这里的的例子就是,利用一个状态机函数(根据不同状态依次调用不同实现方法函数),通过回调
    发表于 12-11 07:23

    如何用函数指针调用函数

    给大家举一个例子: int Func(int x);/*声明一个函数*/ int (*p) (int x);/*定义一个函数指针*/ p = Func; /*将Func函数的首地
    发表于 12-11 06:26

    条件判断法来实现状态机

    状态用 switch—case 组织起来, 将事件也用switch—case 组织起来, 然后让其中一个 switch—case 整体插入到另一个 switch—case 的每一个 case 项中
    发表于 12-09 08:18

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

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

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

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

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

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

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

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