C语言实现状态机(一)

您所在的位置:网站首页 简单的c语言编程实例 C语言实现状态机(一)

C语言实现状态机(一)

2024-02-01 10:04| 来源: 网络整理| 查看: 265

状态机原理

状态机有4个要素:

现态:是指当前所处的状态。条件:又称为“事件”,当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移。动作:条件满足后执行的动作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到新状态。次态:条件满足后要迁往的新状态。“次态”是相对于“现态”而言的,“次态”一旦被激活,就转变成新的“现态”了

举例:

图1

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 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~EVENT5 if(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



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3