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

电子说

1.3w人已加入

描述

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

状态机简介

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

函数指针实现FSM

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

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

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

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

代码实现步骤

定义状态数据的枚举类型

typedef enum {   state_1=1,   state_2,   state_3,   state_4 }State;

定义事件的枚举类型

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

定义状态表的数据类型

typedef struct {     int event;   //事件     int CurState;  //当前状态     void (*eventActFun)();  //函数指针     int NextState;  //下一个状态 }StateTable;

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

void f121() {     printf("this is f121 "); } void f221() {     printf("this is f221 "); } void f321() {     printf("this is f321 "); } void f122() {     printf("this is f122 "); } StateTable fTable[] = {     //{到来的事件,当前的状态,将要要执行的函数,下一个状态}     { 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 },     //add your code here };

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

/*状态机类型*/ typedef struct {     int curState;//当前状态     StateTable * stateTable;//状态表     int size;//表的项数 }fsmType; /*状态机注册,给它一个状态表*/ void fsmRegist(fsmType* pFsm, StateTable* pTable) {     pFsm->stateTable = pTable; } /*状态迁移*/ void fsmStateTransfer(fsmType* pFsm, int state) {     pFsm->curState = state; } /*事件处理*/ void fsmEventHandle(fsmType* pFsm, int event) {     StateTable* pActTable = pFsm->stateTable;     void (*eventActFun)() = NULL;  //函数指针初始化为空     int NextState;     int CurState = pFsm->curState;     int maxNum = pFsm->size;     int flag = 0; //标识是否满足条件     /*获取当前动作函数*/     for (int i = 0; i

附代码

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

测试程序

//编译器:http://www.dooccn.com/cpp/ //来源:技术让梦想更伟大 //作者:李肖遥 #include  typedef enum {   state_1=1,   state_2,   state_3,   state_4 }State; typedef enum{   event_1=1,   event_2,   event_3,   event_4,   event_5 }EventID; typedef struct {     int event;   //事件     int CurState;  //当前状态     void (*eventActFun)();  //函数指针     int NextState;  //下一个状态 }StateTable; void f121() {     printf("this is f121 "); } void f221() {     printf("this is f221 "); } void f321() {     printf("this is f321 "); } void f122() {     printf("this is f122 "); } StateTable fTable[] = {     //{到来的事件,当前的状态,将要要执行的函数,下一个状态}     { 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 },     //add your code here }; /*状态机类型*/ typedef struct {     int curState;//当前状态     StateTable * stateTable;//状态表     int size;//表的项数 }fsmType; /*状态机注册,给它一个状态表*/ void fsmRegist(fsmType* pFsm, StateTable* pTable) {     pFsm->stateTable = pTable; } /*状态迁移*/ void fsmStateTransfer(fsmType* pFsm, int state) {     pFsm->curState = state; } /*事件处理*/ void fsmEventHandle(fsmType* pFsm, int event) {     StateTable* pActTable = pFsm->stateTable;     void (*eventActFun)() = NULL;  //函数指针初始化为空     int NextState;     int CurState = pFsm->curState;     int maxNum = pFsm->size;     int flag = 0; //标识是否满足条件     /*获取当前动作函数*/     for (int i = 0; i

编译结果

编程

总结

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

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

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

责任编辑:haq

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

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分