共4套代码,内容来自网络,代码经过修改
1========================================================
#include <stdio.h>
#include <stdlib.h>
//! 定义状态名称与状态值之间的关系
#define FSM_START 0x00
#define FSM_STATE_A 0x01
#define FSM_STATE_B 0x02
#define FSM_RESET 0xFF
#define FSM_STOP 0xFE
unsigned char inChr='0';
unsigned char fsm_exp_A()
{
static unsigned char state = FSM_START; // 初态
switch (state)
{
case FSM_START: printf_s("fsm_start,press a to StateA or b to StateB or s to Stop\n");
state = FSM_STATE_A;
break;
case FSM_STATE_A: printf_s("cur state is A\n");
if(inChr=='b')
{
state = FSM_STATE_B;printf_s("from A to B when [b] pressed \n");
}
else if(inChr=='s')
{
state = FSM_RESET; printf_s("from A to Stop when [s] pressed \n");
}
break;
case FSM_STATE_B: printf_s("cur state is B\n");
if(inChr=='a')
{
state = FSM_STATE_A; printf_s("from B to A when [a] pressed \n");
}
else if(inChr=='s')
{
state = FSM_RESET; printf_s("from B to Stop when [s] pressed \n");
}
break;
case FSM_RESET: printf_s("in reset state\n");
case FSM_STOP: printf_s("in start state\n");
default: printf_s("fsm is to unknow state");
return 1;
}
return 0;
}
int main(int argc, char *argv[])
{
printf_s("准备进入状态机,press a or b\n");
while(1){
inChr=getchar();
if(fsm_exp_A()) break;
}
return 0;
}
2================================================================
// 多状态位的状态机
#include <stdio.h>
#include <stdlib.h>
//! 首先将布尔量的状态标志压缩在一个字节里面以节省内存开支
typedef union
{
unsigned Value;
unsigned Byte;
struct {
unsigned BIT0:1;
unsigned BIT1:1;
unsigned BIT2:1;
unsigned BIT3:1;
unsigned BIT4:1;
unsigned BIT5:1;
unsigned BIT6:1;
unsigned BIT7:1;
}Bits;
}byte_t;
#define FSM_ACTION_FLAG s_tbState.Bits
#define FSM_STOP_ALL_ACTIONS() do {s_tbState.Value = 0;}while(0)
#define FSM_START (0 == s_tbState.Value)
#define FSM_STATE_A FSM_ACTION_FLAG.BIT0
#define FSM_STATE_B FSM_ACTION_FLAG.BIT1
#define FSM_STATE_C FSM_ACTION_FLAG.BIT2
#define FSM_STATE_D FSM_ACTION_FLAG.BIT3
#define FSM_STATE_E FSM_ACTION_FLAG.BIT4
#define FSM_STATE_F FSM_ACTION_FLAG.BIT5
#define FSM_STATE_G FSM_ACTION_FLAG.BIT6
#define FSM_STATE_H FSM_ACTION_FLAG.BIT7
unsigned char inChr = '0';
unsigned fsm_example_a()
{
printf_s("进入子状态a\n");
if(inChr=='q') return 0;
return 1;
}
unsigned fsm_example_b()
{
static byte_t s_tbState = {0}; //!< 定义状态变量,明确进入 起始状态 0
if (FSM_START)
{
printf_s("进入起始状态A,start装台自动结束\n");
FSM_STATE_A = 1;
}
if (FSM_STATE_A)
{
if (!fsm_example_a())
{
printf_s("离开子状态A,进入父状态B\n");
FSM_STATE_B = 1;
FSM_STATE_A = 0;
}
}
if (FSM_STATE_B)
{
printf_s("进入状态B,一个典型的监视状态\n");
if ( inChr=='c' || inChr=='d') //! 这里检测某些条件(事件)
{
printf_s("准备,同时“开启” C、D 状态的准备工作\n");//! 这里做一些“开启”某个状态的准备工作
FSM_STATE_C = 1; //!< 开启某一个状态而不结束当前状态
FSM_STATE_D = 1; //!< 你当然可以一次触发多个状态
printf_s("已经,同时“开启” B、C、D 状态的准备工作\n");
}
else if (inChr=='B')
{
FSM_STATE_B = 0; printf_s("满足某些条件以后关闭当前状态B\n");
}
else if( inChr=='a')
{
printf_s("进入状态A,仅保留一个状态A");
FSM_STATE_A = 1;
FSM_STATE_B=FSM_STATE_C=FSM_STATE_D=FSM_STATE_E=FSM_STATE_F=FSM_STATE_G=FSM_STATE_H=0;
}
}
if (FSM_STATE_F)
{
if (!fsm_example_a()) //!< 一个典型的子状态机调用
{
//!< 等待子状态机返回false,!子状态机运行完成,进入下一状态
printf_s("等待子状态机返回false,!子状态机运行完成,进入父状态集内,状态F\n");
FSM_STATE_F = 0; //!< 结束当前状态F
FSM_STATE_A = 1; //!< 进入下一状态x代表某个字母
printf_s("结束状态F,进入状态A\n");
}
}
if (FSM_STATE_H)
{ //!< 一个典型的中止状态,某些状态机的操作,比如释放某些资源
printf_s("进入终止状态H,释放资源");
FSM_STOP_ALL_ACTIONS(); //!< 复位状态机
return 0; //!< 返回false表示状态机结束
}
return 1; //!< 返回true表示状态机保持运行
}
int main(int argc, char *argv[])
{
printf_s("准备进入父状态机,press a,b,c,d,e,f,h\n");
while(1){
if(!fsm_example_b()) break;
inChr = getchar();
};
}
3============================================================
// 状态、事件查表法实现
#include <stdio.h>
#include <stdlib.h>
typedef enum {state_1=1,state_2,state_3} State; // 状态可以增加
typedef enum {event_1=1,event_2,event_3,event_4,event_5} EventID; // 事件可以增加
typedef void (*Action)(EventID *);
typedef Action eventAction;
typedef struct
{
State curState; // 现状态
EventID eventId; // 事件ID
State nextState; // 次状态
Action action; // 动作
} StateTransform; // 状态转换结构
typedef struct
{
State state;
int transNum;
StateTransform* transform; // 状态转换集合
}StateMachine; // 状态机对象
StateTransform* findTrans(StateMachine* pSM, const EventID evt)
{
int i;
for ( i = 0; i < pSM->transNum; i++)
{
if ((pSM->transform[i].curState == pSM->state) && (pSM->transform[i].eventId == evt))
{
return &pSM->transform[i]; // 找到下一个状态
}
}
return NULL; // 未找到下一个状态
}
void runStateMachine(StateMachine *pSM,EventID evt)
{
StateTransform* pTrans = findTrans( pSM, evt ); // 查找状态转换表
if ( pTrans == NULL )
{ // 无没有找到状态转换表项目,无次态
printf_s( "初态s%d -> 事件e%d ->无次态\n", pSM->state,evt);
return;
}
State preState = pSM->state; //
pSM->state = pTrans->nextState; // 转移到次态
Action act = pTrans->action; // 执行动作
if (act == NULL) {
printf_s( "初态s%d -> 事件e%d/无动作 -> 次态s%d \n",preState,evt,pSM->state);
return;
}
act(&evt);
}
void f132() { printf_s("现态s%d -> 事件e%d/动作f132->次态s%d \n",state_1,event_3,state_2); }
void f213() { printf_s("现态s%d -> 事件e%d/动作f213->次态s%d \n",state_2,event_1,state_3); }
void f242() { printf_s("现态s%d -> 事件e%d/动作f242->次态s%d \n",state_2,event_4,state_2); }
void f321() { printf_s("现态s%d -> 事件e%d/动作f321->次态s%d \n",state_3,event_2,state_1); }
void f332() { printf_s("现态s%d -> 事件e%d/动作f332->次态s%d \n",state_3,event_3,state_2); }
void f353() { printf_s("现态s%d -> 事件e%d/动作f353->次态s%d \n",state_3,event_5,state_3); }
int run()
{
StateMachine stateMachine; // 状态机对象
stateMachine.state = state_1; // 初态
stateMachine.transNum = 7; // 可状态转换数量
StateTransform stateTran[] = { // 状态转换表集合,共7个状态转换
{state_1,event_3,state_2,f132}, // S1-> e3/f121 -> S2
{state_1,event_4,state_2,NULL},
{state_2,event_1,state_3,f213},
{state_2,event_4,state_2,f242},
{state_3,event_2,state_1,f321},
{state_3,event_3,state_2,f332},
{state_3,event_5,state_3,f353},
};
stateMachine.transform = stateTran;
EventID inputEvent[15] = { // 顺序输入15个事件
event_1, event_2, event_3, event_4, event_5,
event_1, event_2, event_3, event_4, event_5,
event_1, event_2, event_3, event_4, event_5
};
int i;
for (i = 0; i < 15; i++)
{
runStateMachine(&stateMachine, inputEvent[i]); //状态机对象,输入事件
}
return 0;
}
int main(int argc, char *argv[])
{
printf_s("C语言实现状态机\n-----------------------------\n");
run();
return 0;
}
4============================================================
// 这个也是查表方式,带头文件 fsm.h
#ifndef _FSM_H_
#define _FSM_H_
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
typedef enum { walk_state=1,talk_state,fly_state,run_state,jump_state } FSM_STATE, *FSM_STATE_P; // 状态集合
typedef enum { walk_event=1,talk_event,fly_event,run_event,jump_event } FSM_EVENT, *FSM_EVENT_P; // 事件集合
typedef void(*EAF)(void *); // 动作函数类型声明;
typedef EAF EventActFun; // 类型定义
// 状态表结构
typedef struct FsmTable_s
{
uint8_t event; // 事件
uint8_t CurState; // 现态
//void (*eventActFun)(void *); // 动作,函数指针类型不明确
EventActFun eventActFun; // 动作,使用明确的类型
uint8_t NextState; // 次态
}FsmTable_T,*FsmTable_T_P;
// 状态机对象
typedef struct FSM_s
{
FsmTable_T *FsmTable; // 状态表空间
uint8_t curState; // 现态
uint8_t stuMaxNum;
} FSM_T, *FSM_T_P ;
void FSM_Regist(FSM_T *pFsm, FsmTable_T *pTable, uint8_t stuMaxNum, uint8_t curState);
void FSM_EventHandle(FSM_T *pFsm, uint8_t event, void *parm);
#endif
// main.c
/* https://blog.csdn.net/weixin_44088559/article/details/105539313
C语言实现简单有限状态机(FSM) */
#include "fsm.h"
// 状态转换
static void FSM_StateTransfer(FSM_T *pFsm, uint8_t state)
{
pFsm->curState = state;
}
// 状态机处理函数, pFsm状态机对象, event触发事件, parm动作执行参数
void FSM_EventHandle(FSM_T *pFsm, uint8_t event, void *parm)
{
FsmTable_T *pAcTable = pFsm->FsmTable;
EventActFun actionFun = NULL; // void (*ventActFun)(void *) = NULL;
uint8_t CurState = pFsm->curState; // 现态
uint8_t flag = 0; // 状态转换标记
uint8_t NextState;
for (uint8_t i = 0; i < pFsm->stuMaxNum; i++)
{
if (event == pAcTable[i].event && CurState == pAcTable[i].CurState)
{
flag = 1;
actionFun = pAcTable[i].eventActFun;
NextState = pAcTable[i].NextState;
break;
}
}
if (flag)
{
if (actionFun != NULL) { actionFun(parm); } // 执行动作
FSM_StateTransfer( pFsm, NextState ); // 转到次态
}
}
//状态机注册 : pFsm状态机对象,pTable状态迁移表,stuMaxNum迁移表数量
void FSM_Regist(FSM_T *pFsm, FsmTable_T *pTable, uint8_t stuMaxNum, uint8_t curState)
{
pFsm->FsmTable = pTable; // 状态空间表
pFsm->curState = curState; // 初状态
pFsm->stuMaxNum = stuMaxNum; // 状态数量
}
//函数声明
void walk(void * );
void talk(void * );
void fly( void * );
void run( void * );
void jump(void * );
//main.c
int main(int argc, char *argv[])
{
FSM_T fsm = { 0} ; /*创建FSM_T对象*/
FSM_T_P fsm_p = &fsm;
/* 创建FsmTable_T表 */
FsmTable_T fsm_table[5] =
{
{ walk_event, walk_state, walk, talk_state },
{ talk_event, talk_state, talk, run_state },
{ fly_event, fly_state, fly, jump_state },
{ run_event, run_state, run, fly_state },
{ jump_event, jump_state, jump, walk_state }
};
char i = 1;
FSM_Regist( fsm_p, fsm_table, 5, walk_state); /*FSM_Init()初始化*/
int EVENT = 0; // 事件标记
while(1)
{
FSM_EventHandle( fsm_p, EVENT, &i); /*轮询运行状态机*/
//EVENT++;
if(EVENT++>5) EVENT = 1;
//getchar();
}
return 0;
}
//函数实现
void walk(void * t){ printf("我正在走\r\n"); }
void talk(void * t){ printf("我正在讲话\r\n"); }
void fly(void * t){ printf("我正在飞机上\r\n"); }
void run(void * t ){ printf("我正在跑步\r\n"); }
void jump(void * t){ printf("我正在跳高\r\n"); }
5========================================================
#include <stdio.h>
#include <conio.h> //获取键盘建值状态
typedef enum { event1 = 0x31, event2, event3, event4, event5, event6, event7, event8} SEvent;//所有事件的集合
typedef enum { state1 = 1, state2, state3, state4, state5} CState; //所有状态的集合
typedef struct {
int Event;//触发的事件
int Curstate;//当前状态
void (*CallBack)();//触发之后的回调函数
int Nextstate;//下一个状态
}State_table;//状态表
typedef struct {
int Curstate;//当前状态
State_table* Stable;//状态表
int Stable_size;//状态表的项数
}FSM;//实际操作的状态机对象
/*状态机注册,给它一个状态表
pFsm 新建的状态机
pTable 传入的状态机对应表
state 初始默认状态*/
void FSM_Regist(FSM* pFsm, State_table *pTable, CState state,int TableSize)
{
pFsm->Stable = pTable;//传入所给的状态表
pFsm->Stable_size= TableSize;//所给状态表的大小
pFsm->Curstate = state;//当前的默认状态
}
void FSM_EventHandle(FSM *pFsm, SEvent event) {//注意这里要传入的pFsm必须是一个指针,不然改不了状态
void (*ActionCallBack)();
ActionCallBack = 0;//默认置空
for (int i = 0; i < pFsm->Stable_size; i++) {
if (pFsm->Curstate == pFsm->Stable[i].Curstate && event == pFsm->Stable[i].Event) {
ActionCallBack = pFsm->Stable[i].CallBack;//找出要执行的函数
pFsm->Curstate = pFsm->Stable[i].Nextstate;//更改状态
}
}
if (ActionCallBack != 0) {
ActionCallBack();//动作执行
}
else return;
}
void thing1() { printf("这里是执行函数1 \r\n");}
void thing2() { printf("这里是执行函数2 \r\n");}
void thing3() { printf("这里是执行函数3 \r\n");}
void thing4() { printf("这里是执行函数4 \r\n");}
void thing5() { printf("这里是执行函数5 \r\n");}
State_table STranTable[] = {
{ event1, state1, thing1, state2 },
{ event2, state2, thing2, state3 },
{ event3, state3, thing3, state4 },
{ event4, state4, thing4, state5 },
{ event5, state5, thing5, state5 },
{ event1, state5, thing1, state1 },
{ event3, state3, thing1, state5 },
};
int main(void)
{
FSM Mfsm;
FSM_Regist(&Mfsm, STranTable, state1,sizeof(STranTable)/sizeof(State_table));
while (1) {
while (_kbhit()) {
SEvent key = (SEvent)_getch();
FSM_EventHandle(&Mfsm, key);
}
}
}