一、状态机简介
有限状态机(FSM)是表示有限个状态及在这些状态之间的转移和动作等行为的数学模型,通常FSM包含几个要素:状态的管理、状态的监控、状态的触发、状态触发后引发的动作。
1.1 重点概念
1、数学语言描述如下:一个有限状态机M是一个五元组,M=(K,E,T,S,Z)。其中(1)K是一个有穷集,其中的每个元素称为状态(2)E是一个有穷字母表,它的每个元素称为一个输入字符(3)T是转换函数,是K×E->K上的映射(4)S是K中的元素,是唯一的一个初态(5) Z是K的一个子集,是一个终态集,或者叫结束集。
2、软件设计领域中通用状态机的输入不是字符集,而是被称作事件的结构(可以是结构体,也可以是类对象),并且特定的状态下,针对发生的事件,不仅发生状态改变,而且产生动作。借鉴编译原理中状态机的初始状态和终态,通用状态机的数学语言描述如下:一个通用有限状态机M是一个七元组,M={K,E,T,M,F,S,Z}。其中(1)K是一个有穷集,其中的每个元素称为状态(2)E是一个有穷集,它的每个元素称为一个事件(3)T是转换函数,是K×E->K上的映射(4)M是一个有穷集,它的每个元素称为动作(5)F是动作映射函数,是K×E->M上的映射(6)S是K中的元素,是唯一的一个初态(7) Z是K的一个子集,是一个终态集,或者叫结束集。
二、软件设计
2.1 switch case/if else设计方法
curEvent = getEvent();
curState = getCurState();
switch(curState)//什么状态
{
case state1:
{
switch(curEvent )//发生什么事
{
TODO...
setCurState();
break;
}
break;
}
...
}
2.2、利用数据结构
基于表结构的状态机设计方法:建立相应的状态表和动作查询表,根据状态表、事件、动作表定位相应的动作处理函数,执行完成后再进行状态的切换。
通过设计一个通用的基于表结构的状态机模块,针对不同的状态图,我们只需要根据状态图得到其状态表结构,然后通过FSM_Regist注册,就可以方便的使用了状态机的功能了。这种机制便于我们添加新的状态流程,并且可以很好的进行分层状态机的设计。
/*状态表注册*/
void FSM_Regist(FSM_T* pFsm,STATE_TABLE_S* pStateTable)
{
pFsm->FsmTable = pStateTable;
return;
}
/*状态迁移*/
void FSM_MoveState(FSM_T* pFsm,int state)
{
pFsm->curState = state;
return;
}
/*事件处理*/
void FSM_EventHandle(FSM_T* pFsm,int event)
{
ACT_TABLE_T* pActTable = NULL;
ActFun eventActFun = NULL;
/*获取当前状态动作表*/
pActTable = FSM_getActTable(pFsm);
/*获取当前动作函数*/
for(int i=0;i<MAX_ACT_NUM;i++)
{
if(event == pActTable[i].event)
{
eventActFun = pActTable[i].eventActFun;
break;
}
}
/*动作执行*/
if(eventActFun)
{
eventActFun(pFsm);
}
}
三、FSM的实现
3.1 FSM需实现以下接口
#ifndef FSM_H
#define FSM_H
#define MAX_FSM_NUM 10 /**最大状态机的数目*/
typedef void (*fsm_event_func)(void*);
typedef struct
{
int event; /**事件标示*/
fsm_event_func func; /**事件函数*/
}event_table_t;
typedef struct
{
int state; /**状态标示*/
int event_size; /**事件表大小*/
event_table_t *event_table; /**事件表信息*/
}st_table_t;
typedef struct
{
int state; /**状态标示*/
int st_size; /**状态表大小*/
st_table_t *st_table; /**状态表信息*/
}fsm_stack_t;
typedef struct
{
int fsm_id; /**状态机标示*/
int st_size; /**状态表大小*/
st_table_t *st_table; /**状态表信息*/
}fsm_regist_t;
typedef struct
{
int cur_st; /**当前状态标示*/
int cur_st_size; /**当前状态表大小*/
st_table_t *cur_fsm_table; /**当前状态机信息*/
fsm_stack_t stack[MAX_FSM_NUM]; /**入栈状态机的信息*/
fsm_regist_t regist_fsm[MAX_FSM_NUM]; /**注册状态机的信息*/
}fsm_t;
void fsm_pop(fsm_t *fsm);
void fsm_push(fsm_t *fsm);
void fsm_init(fsm_t *fsm);
void fsm_begin(fsm_t *fsm, int fsm_id);
int fsm_delete(fsm_t *fsm, int fsm_id);
void fsm_move_st(fsm_t *fsm, int state);
void fsm_event_handle(fsm_t *fsm, int event);
int fsm_regist(fsm_t *fsm, st_table_t *st_table, int fsm_id, int talbe_size);
#endif
完整代码参考:https://download.csdn.net/download/qq_31441951/12431241
未完待续~~~