C语言实现状态机(一)
状态机原理
状态机有4个要素:
- 现态:是指当前所处的状态。
- 条件:又称为“事件”,当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移。
- 动作:条件满足后执行的动作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到新状态。
- 次态:条件满足后要迁往的新状态。“次态”是相对于“现态”而言的,“次态”一旦被激活,就转变成新的“现态”了
举例:
STATE1是现态,STATE2是次态,EVENT是条件,action是动作。当产生EVENT时,触发action,action执行完毕后从STATE1迁移到STATE2,此时,STATE2为现态。
在这个例子中,action只是一个瞬时执行的动作,它只在现态迁移到次态的过程中执行,当迁移完成后,action不再执行。
对以上状态机模型进行改进:
STATE1是现态,STATE2是次态,EVENT是条件,动作分为entry、do、exit三步,而且STATE1和STATE2都有动作entry、do、exit(注意:STATE1中的entry、do、exit和STATE2中的entry、do、exit不是同一个东西,可以将STATE1理解为一个结构体变量,而entry、do、exit是结构体的元素)。假设现在没有触发条件EVENT,现态STATE1持续执行do动作(注意:持续执行的意思不止执行一次),直到触发条件EVENT产生,此时STATE1不再执行do动作,而是执行exit动作,执行完后执行STATE2中的entry动作,并将现态更新为STATE2,STATE2持续执行do动作。
改进后的状态机模型有很多好处,举个例子:如在STATE1这个状态下对计数器COUNT进行计数,使用改进后的状态机模式可以这样做:
(1)在STATE1的entry里面对COUNT进行初始化
(2)在STATE1的do里面对COUNT进行计数
(3)在STATE1的exit里面对COUNT进行复位
C语言实现状态机
假设有状态机流程图如图:
定义枚举类型STATE_t表示状态机状态:
typedef enum{STATE1 = 0,STATE2,STATE3,STATE4,
}STATE_t;
定义ACTION_MAP_t结构体类型,表示状态机状态属性:
typedef void (*STATE_ACTION)(void);
typedef struct ACTION_MAP
{STATE_t stStateID;STATE_ACTION EnterAct; STATE_ACTION RunningAct; STATE_ACTION ExitAct;
}ACTION_MAP_t;
建立“动作”表:
void state1_entry(void)
{printf("state1_entry\n");
}
void state1_do(void)
{printf("state1_do\n");
}
void state1_exit(void)
{printf("state1_exit\n");
}void state2_entry(void)
{printf("state2_entry\n");
}
void state2_do(void)
{printf("state2_do\n");
}
void state2_exit(void)
{printf("state1_exit\n");
}void state3_entry(void)
{printf("state3_entry\n");
}
void state3_do(void)
{printf("state3_do\n");
}
void state3_exit(void)
{printf("state3_exit\n");
}void state4_entry(void)
{printf("state4_entry\n");
}
void state4_do(void)
{printf("state4_do\n");
}
void state4_exit(void)
{printf("state4_exit\n");
}
ACTION_MAP_t actionMap[] =
{{STATE1, state1_entry, state1_do, state1_exit},{STATE2, state2_entry, state2_do, state2_exit},{STATE3, state3_entry, state3_do, state3_exit},{STATE4, state4_entry, state4_do, state4_exit},
};
定义枚举类型EVENT_t表示事件:
typedef enum
{EVENT1 = 0,EVENT2,EVENT3,EVENT4,EVENT5,EVENT_MAP_END
}EVENT_t;
注:定义EVENT_MAP_END的目的是为了方便查表。
定义EVENT_MAP_t结构体类型,表示事件表属性:
typedef struct EVENT_MAP
{EVENT_t stEventID;STATE_t stCurState;STATE_t stNextState;
}EVENT_MAP_t;
根据状态机流程图建立事件表:
EVENT_MAP_t eventMap[] =
{{EVENT1, STATE1, STATE2},{EVENT2, STATE2, STATE3}, {EVENT3, STATE3, STATE4},{EVENT4, STATE4, STATE1},{EVENT5, STATE1, STATE4},{EVENT_MAP_END, 0, 0},
};
定义状态机结构体类型:
typedef struct FSM
{STATE_t stCurState;STATE_t stNextState;ACTION_MAP_t *pActionMap;EVENT_MAP_t *pEventMap;
}FSM_t;
定义状态机注册函数:
void fsm_init(FSM_t* pFsm,EVENT_MAP_t* pEventMap,ACTION_MAP_t *pActionMap)
{pFsm->stCurState = 0;pFsm->stNextState = EVENT_MAP_END;pFsm->pEventMap = pEventMap;pFsm->pActionMap = pActionMap;
}
定义状态机转换函数:
void fsm_state_transfer(FSM_t* pFsm, EVENT_t stEventID)
{uint8_t i = 0;for(i=0; pFsm->pEventMap[i].stEventID<EVENT_MAP_END; i++){if((stEventID == pFsm->pEventMap[i].stEventID) && (pFsm->stCurState == pFsm->pEventMap[i].stCurState)){pFsm->stNextState = pFsm->pEventMap[i].stNextState;return;}}
}
定义动作执行函数:
void action_perfrom(FSM_t* pFsm)
{if(EVENT_MAP_END != pFsm->stNextState){pFsm->pActionMap[pFsm->stCurState].ExitAct();pFsm->pActionMap[pFsm->stNextState].EnterAct();pFsm->stCurState = pFsm->stNextState;pFsm->stNextState = EVENT_MAP_END;}else{pFsm->pActionMap[pFsm->stCurState].RunningAct();}
}
测试:
int main(void)
{int i = 0; FSM_t stFsmWeather; //定义状态机fsm_init(&stFsmWeather,eventMap,actionMap); //注册状态机while(1){usleep(10);printf("i = %d\n",i++);action_perfrom(&stFsmWeather);//利用i产生EVENT1~EVENT5if(0 == (i%11)){fsm_state_transfer(&stFsmWeather,EVENT1);}if(0 == (i%31)){fsm_state_transfer(&stFsmWeather,EVENT2);}if(0 == (i%74)){fsm_state_transfer(&stFsmWeather,EVENT3);}if(0 == (i%13)){fsm_state_transfer(&stFsmWeather,EVENT4);} if(0 == (i%19)){fsm_state_transfer(&stFsmWeather,EVENT5);}}return 0;
}
https://blog.csdn.net/qq_36969264/article/details/122365696
C语言实现状态机(一)相关推荐
- 设计模式的C语言应用-状态机模式-第二章
模式介绍 状态(state)模式是C语言实现相当常用的模式,也是能够在C语言***现出来的最显性的模式之一.在面向对象里,状态模式允许一个对象在内部状态改变的时候改变其行为. 状态用法很多,最常见的是 ...
- C语言实现状态机(二)
前言 对于之前的一篇博客<C语言实现状态机>(链接:https://blog.csdn.net/qq_36969264/article/details/105865099?spm=1001 ...
- 基于VHDL语言的状态机设计
基于VHDL语言的状态机(FSM)设计 状态机(Finite State Machine,FSM) 状态机的组成:如图所示 状态机的种类: Mealy型:当前状态.当前输入相关 Moore型:仅当前状 ...
- c语言按键状态机,C语言状态机编程思想
原标题:C语言状态机编程思想 有限状态机概念 有限状态机是一种概念思想,把复杂的控制逻辑分解成有限个稳定状态,组成闭环系统,通过事件触发,让状态机按设定的顺序处理事务.单片机C语言的状态机编程,是利用 ...
- <C语言>C语言实现状态机
C语言实现状态机 状态机模式适用于有限状态下程序按照逻辑循环执行,相较于在while循环中通过if else判断状态标志来执行相应的动作,状态机模式能够灵活的增加.减少状态,程序逻辑更为清晰 ...
- C语言用状态机来实现简单的密码开锁
功能描述:用户连续输入正确的密码则会开锁,如果密码输入过程错误则锁会退回到初始状态,重新键入密码,即:用户只需要连续输入正确的密码即可开锁(输入错误不用撤销.也不用删除) 以上的分析和下面的代码来自& ...
- 语言用加法实现加饭运算_「编程之美」用C语言实现状态机(超实用)
关于状态机,基础的知识点可以自行理解,讲解的很多,这里主要是想写一个有限状态机FSM通用的写法,目的在于更好理解,移植,节省代码阅读与调试时间,体现出编程之美. 传统的实现方案 if...else : ...
- c语言中状态机的作用,C语言中的状态机
用C编写状态机的最佳方法是什么? 我通常在for(;;)中编写一个大的switch-case语句,并使用回调在外部操作完成后重新进入状态机. 您知道更有效的方法吗? 这似乎是一种非常标准的实现方法. ...
- C语言--实现状态机
关于状态机,基础的知识点可以自行理解,讲解的很多,这里主要是想写一个有限状态机FSM通用的写法,目的在于更好理解,移植,节省代码阅读与调试时间,体现出编程之美. 传统的实现方案 if...else : ...
最新文章
- Assembly and diploid architecture of an individual human genome via single-molecule technologies
- ASP.NET MVC WebAPI实现文件批量上传
- 设置TextField内文字距左边框的距离
- 【树莓派】树莓派(Debian)- root用户无法使用SSH登录
- Java 多线程 通信 通道 (猫狗赛跑)
- 伏安特性曲线实验报告_【鼎阳硬件智库原创 | 测试测量】动手测量电解电容器的阻抗频率特性...
- python编程入门书籍-编程小白的第一本 Python 入门书
- eclipse创建测试apk文件的测试工程,报错java.lang.NullPointerException
- 【倒计时】用JS写出京东倒计时效果
- android 自动打开钉钉,安卓定时自动打开钉钉考勤打卡
- 自然语言处理中的伪数据 by哈工大教授车万翔
- USB接口类型及引脚定义-usb1.0,usb2.0,usb3.0,Type-c
- 奇异值分解推导详解以及几何意义
- win10计算机升级系统,微软Win10升级助手
- 电子计算机显示屏不亮了,手把手教你电脑显示器不亮怎么办
- KVM-1、Linux 操作系统及虚拟化
- 代码写一半感觉无从下手,写不下去了,怎么办?
- Apsara Clouder基础技能认证:阿里巴巴编码规范相关问题总结
- python使用163邮箱发送邮件
- 复制文件或文件夹时出错(无法复制***:没有足够的可用磁盘空间。) .