fsm
简介
Finite-State Machines(fsm), 有限状态机。嵌入式系统开发会遇到很多的状态机,简单的状态机,也有复杂系统的状态机。一个门的状态机,autosar 中的网络管理的状态机,CANSM的状态机.....。使用状态机可以简化复杂的系统。
一般写C语言都是,按照解决问题的步骤一步一步写。叫面向过程。
状态机的写法是面向对象的写法,构造了一个状态机数据结构,这个数据结构描述了状态和事件之间的关系 ,状态机会根据事件的输入和当前的状态,切换到下一个状态,并且做出相应的动作。
一般状态机都需要有以下的几个属性:
有限数量的状态,系统处于其中之一
有限数量的事件
对应转换状态的动作
对所有状态转化的明确规定(当状态机处于某个状态并且输入特定事件时做什么动作)
具体怎么去写,就是根据当前的状态,发生事件后,转移到下一个状态,决定执行的动作。
还是以一个简单的状态机举个例子,分享一下三种写法。具体项目的状态机需要进行改进和优化。
OK,我们以一个车门当做例子。
不管用什么办法去写,都需要先定义下面的数据类型
定义状态枚举 、定义事件枚举、创建对应事发送后的动作函数
switch_case 或者 if else 实现
//fsm
// 定义状态枚举
typedef enum {
CLOSE,
OPEN,
LOCK,
NUM_STATES
} state_eum;
// 定义事件枚举
typedef enum {
CLOSEED,{
OPENED,
LOCKED,
UNLOCKED,
NUM_EVENTS
} event_eum;
// 声明状态函数的原型
typedef void (*statefunction)(void *param);
//定义状态机结构体
typedef struct DoorStateMachine_
{
state_eum current_state;
statefunction table[NUM_EVENTS];
}statemachine_st;
// 声明状态处理函数
void handler_close(void *param);
void handler_open(void *param);
void handler_lock(void *param);
void handler_unlock(void *param);
statemachine_st machine;
#include <stdio.h>
#include "fsm.h"
// 定义状态处理函数数组
statefunction state_function[NUM_EVENTS] = {
handler_close,
handler_open,
handler_lock,
handler_unlock
};
// 状态机初始化函数
void DoorManager_Init();
// 状态机主函数
void triggerEvent(event_eum event);
//对应状态下的动作
void handler_close(void *param) {
printf("close door\n");
printf("Transitioning to Close\n");
machine.current_state = CLOSE;
}
void handler_open(void *param) {
printf("open door\n");
printf("Transitioning to Open \n");
machine.current_state = OPEN;
}
void handler_lock(void *param) {
printf("lock door\n");
printf("Transitioning to Lock \n");
machine.current_state = LOCK;
}
void handler_unlock(void *param){
printf("unlock door\n");
printf("Transitioning to Close \n");
machine.current_state = CLOSE;
}
void DoorManager_Init(){
int i = 0;
machine.current_state = CLOSEED;
for ( i = 0; i < NUM_EVENTS; i++)
{
machine.table[i] = state_function[i];
}
}
void triggerEvent(event_eum event){
switch (event)
{
case CLOSEED:
if(machine.current_state == OPEN){
machine.table[CLOSEED](NULL);
}
else{
printf("No transition defined for this event in the current state.\n");
}
break;
case OPENED:
if(machine.current_state == CLOSE){
machine.table[OPENED](NULL);
}
else{
printf("No transition defined for this event in the current state.\n");
}
break;
case LOCKED:
if(machine.current_state == CLOSE){
machine.table[LOCKED](NULL);
}
else{
printf("No transition defined for this event in the current state.\n");
}
break;
case UNLOCKED:
if(machine.current_state == LOCK){
machine.table[UNLOCKED](NULL);
}
else{
printf("No transition defined for this event in the current state.\n");
}
break;
default:
printf("No defined event\n");
break;
}
}
void main(){
event_eum event;
DoorManager_Init();
while (1)
{
printf("Enter event: ");
scanf("%d", &event);
triggerEvent(event);
}
}
状态转换表实现
状态机也可以描述成下面的这个一张表
//fsm1
// 定义状态枚举
typedef enum {
CLOSE,
OPEN,
LOCK,
NUM_STATES
} state_eum;
// 定义事件枚举
typedef enum {
CLOSEED,
OPENED,
LOCKED,
UNLOCKED,
NUM_EVENTS
} event_eum;
// 声明状态函数的原型
typedef void (*statefunction)(void *param);
//状态转移表
typedef struct FsmTable_
{
event_eum event; //事件
state_eum current_state; //当前状态
statefunction action; //action
state_eum next_state; //下一个状态
}FsmTable_st;
//定义状态机结构体
typedef struct DoorStateMachine_
{
state_eum current_state;
FsmTable_st* table;
}statemachine_st;
// 声明状态处理函数
void handler_close(void *param);
void handler_open(void *param);
void handler_lock(void *param);
void handler_unlock(void *param);
#include <stdio.h>
#include "fsm1.h"
statemachine_st machine;
FsmTable_st FsmTable[NUM_EVENTS] = {
{CLOSEED,OPEN,handler_close,CLOSE},
{OPENED,CLOSE,handler_open,OPEN},
{LOCKED,CLOSE,handler_lock,LOCK},
{UNLOCKED,LOCK,handler_unlock,CLOSE}
};
//对应状态下的动作
void handler_close(void *param) {
printf("close door\n");
printf("Transitioning to Close\n");
machine.current_state = CLOSE;
}
void handler_open(void *param) {
printf("open door\n");
printf("Transitioning to Open \n");
machine.current_state = OPEN;
}
void handler_lock(void *param) {
printf("lock door\n");
printf("Transitioning to Lock \n");
machine.current_state = LOCK;
}
void handler_unlock(void *param){
printf("unlock door\n");
printf("Transitioning to Close \n");
machine.current_state = CLOSE;
}
void DoorManager_Init(){
machine.current_state = CLOSEED;
machine.table = FsmTable;
}
void triggerEvent(event_eum event){
if(event >= NUM_EVENTS){
printf("No defined event\n");
goto err;
}
int i = 0;
for (i = 0;i < NUM_EVENTS; i++)
{
if(machine.table[i].event == event && machine.table[i].current_state == machine.current_state){
machine.table[i].action(NULL);
break;
}
}
if(NUM_EVENTS == i){
printf("No transition defined for this event in the current state.\n");
}
err:
}
void main(){
event_eum event;
DoorManager_Init();
while (1)
{
printf("Enter event: ");
scanf("%d", &event);
triggerEvent(event);
}
}
state_event 实现
状态机,还可以看做是一张二维的表。表的x 为state,y为event(也可以倒过来,看你怎么写)。
// fsm2
// 定义状态枚举
typedef enum {
CLOSE,
OPEN,
LOCK,
NUM_STATES
} state_eum;
// 定义事件枚举
typedef enum {
CLOSEED,
OPENED,
LOCKED,
UNLOCKED,
NUM_EVENTS
} event_eum;
// 声明状态函数的原型
typedef void (*statefunction)(void *param);
// 定义状态机数据结构
typedef struct {
state_eum current_state; // 当前状态
statefunction table[NUM_STATES][NUM_EVENTS]; // 状态转移表
} statemachine_st;
// 声明状态处理函数
void handler_close(void *param);
void handler_open(void *param);
void handler_lock(void *param);
void handler_unlock(void *param);
#include <stdio.h>
#include "fsm2.h"
// 设定state_event表
statefunction state_event[NUM_STATES][NUM_EVENTS] = {
{NULL, handler_open, handler_lock, NULL},
{handler_close, NULL, NULL, NULL},
{NULL, NULL, NULL, handler_unlock}
};
//创建状态机
statemachine_st machine;
//对应状态下的动作
void handler_close(void *param) {
printf("close door\n");
printf("Transitioning to Close\n");
machine.current_state = CLOSE;
}
void handler_open(void *param) {
printf("open door\n");
printf("Transitioning to Open \n");
machine.current_state = OPEN;
}
void handler_lock(void *param) {
printf("lock door\n");
printf("Transitioning to Lock \n");
machine.current_state = LOCK;
}
void handler_unlock(void *param){
printf("unlock door\n");
printf("Transitioning to Close \n");
machine.current_state = CLOSE;
}
void init_statemachine(statemachine_st *machine) {
// 设定初始状态
machine->current_state = CLOSE;
// 设定状态转移表
for (int i = 0; i < NUM_STATES; ++i) {
for (int j = 0; j < NUM_EVENTS; ++j) {
machine->table[i][j] = state_event[i][j];
}
}
}
// 触发事件
void triggerEvent(statemachine_st *machine, event_eum event) {
if(event >= NUM_EVENTS){
printf("No defined event\n");
goto err;
}
// 获取当前状态对应的函数
statefunction func = machine->table[machine->current_state][event];
// 调用函数
if (func != NULL) {
func(NULL);
} else {
printf("No transition defined for this event in the current state.\n");
}
err:
}
// 测试状态机
int main() {
event_eum event;
// 初始化状态机
init_statemachine(&machine);
while (1) {
printf("Enter event: ");
scanf("%d", &event);
triggerEvent(&machine, event);
}
return 0;
}