状态机思维
状态机思维可以更好的描述系统的行为,方便整个系统逻辑的理解和后期程序的管理。
简介
回主目录
状态机(State Machine)在嵌入式软件编程中是很常见的一种编程思想,它是一种描述和处理系统行为的模型,将系统划分为一组离散的状态,定义了状态之间的转换条件和操作。
状态机由状态(State)
、状态转换条件(Transition)
、动作(Action)
、初始状态(Initial State)
和初始状态(Initial State)
组成。
类型
状态机可以分为两种类型:有限状态机(FSM)和无限状态机(USM)。
- 有限状态机(FSM)是最常见的状态机实现方式。它由确定的状态、预定义的转移条件和对应的动作组成。程序根据当前状态和输入条件,进行状态转移和执行相应的动作。
- 无限状态机(USM)是一种更灵活的状态机实现方式,状态和转移条件可以动态生成和修改。USM通常使用状态模式进行实现,状态之间通过递归调用实现转移,可以处理更复杂的状态转移逻辑。
实现方式:
- 条件逻辑编码法:这种方法通过编写代码来直接实现状态机的转换和动作。一般使用switch语句或、if-else语句或者函数指针等方式来处理不同的事件和状态转换。
- 表驱动法:这种方法利用数据结构来存储状态及其对应的转换条件和动作。通常使用状态转换表(State Transition Table)或状态转换图(State Transition Diagram)来描述状态机的行为。在C语言中,可以使用表格(如二维数组)来表示状态及其转换。通过查表即可根据当前状态和输入事件找到下一个状态,执行相应的动作。
- 状态模式:使用面向对象的方式,将状态抽象为类,每个状态类实现自己的行为和状态迁移逻辑。
基本步骤
-
定义状态:根据具体系统需求,确定状态的数据和含义。每个状态都有一个标识符来表示。
-
定义状态转换条件:确定触发状态转换的条件,即从一个状态转移到另一个状态所需的条件。如输入事件、定时器等。
-
定义动作:确定每个状态下需要执行的动作操作,如更新数据、发送消息等。
-
实现状态机逻辑:将状态、转换条件和动作组织起来,使用代码实现状态机逻辑。可以定义状态机的数据结构和函数,数据结构通常包含当前状态、状态转换表等信息。函数可以用来处理状态转换、执行状态转换动作等。
-
测试和调试:通过测试验证状态机的正确性和稳定性,修复存在的问题。
框架
一、条件逻辑编码
模型一:
/*定义状态A,B,C,每个状态标识一个特定的行为或状态*/
typedef enum{
STATE_A,
STATE_B,
STATE_C,
// ...
} State;
/*定义状态转换条件,开始和停止*/
typedef enum{
EVENT_START,
EVENT_STOP
} Event;
/*实现状态机逻辑*/
void processEvent(Event event,State *currentState)
{
/*根据当前的状态执行对应的动作*/
switch (*currentState) {
case STATE_A:
if (event == EVENT_START)
{
// 状态转移到状态B,执行状态转移时会产生的动作
*currentState = STATE_B;
……
}
break;
case STATE_B:
if (event == EVENT_STOP)
{
//状态转移到状态C,执行状态转移时会产生的动作
*currentState = STATE_C;
……
}
break;
case STATE_C:
// 停止
break;
default:
// 错误处理
printf("错误的状态\n"); /*根据语法规范,错误时最好有个日志输出,方便Debug*/
break;
}
}
int main()
{
State currentState = STATE_A;
processEvent(EVENT_START, ¤tState); //此时跳转到了状态B
processEvent(EVENT_STOP, ¤tState); //此时跳转到了状态C
return 0;
}
模型二:
/*定义状态A,B,C,每个状态标识一个特定的行为或状态*/
typedef enum {
STATE_A,
STATE_B,
STATE_C,
// ...
} State;
/*实现状态机逻辑*/
int main()
{
while(1)
{
switch (current_state)
{
case STATE_A:
// 处理状态A的逻辑
// ...
if(/* 满足某个条件 */)
{
/*触发状态转换条件,状态跳转*/
current_state = STATE_B;
}
else if(/* 满足某个条件 */)
{
current_state = STATE_C;
}
break;
case STATE_B:
// 处理状态B的逻辑
// ...
current_state = STATE_C;
break;
case STATE_C:
// 处理状态C的逻辑
// ...
current_state = STATE_A;
break;
// ...
}
}
}
二、表驱动法
回主目录
表驱动法通过使用一张状态转换表来实现状态机。这张表保存了状态转换的信息,程序会根据当前状态和输入来查找对应的状态转换,并执行相应的操作。
#include <stdio.h>
/*定义状态A,B,C,每个状态标识一个特定的行为或状态*/
typedef enum {
State_A,
State_B,
State_C
} State;
// 定义输入事件
typedef enum {
Event_1,
Event_2
} Event;
// 定义状态转换表
typedef struct {
/*当前状态-当前事件-下个状态-动作*/
State current_state;
Event current_event;
State next_state;
void (*action)();
} Transition;
// 定义状态转换表数组
Transition transitions[] = {
/*当前状态-当前事件-下个状态-动作*/
{State_A, Event_1, State_B, action1},
{State_A, Event_2, State_C, action2},
// ... 其他状态转换
};
/*根据当前状态和输入事件在定义的表里面查找相应状态转换*/
Transition* findTransition(State current_state, Event current_event) {
for (int i = 0; i < sizeof(transitions) / sizeof(transitions[0]); i++) {
if (transitions[i].current_state == current_state &&
transitions[i].current_event == current_event) {
return &transitions[i];
}
}
return NULL;
}
// 执行相应的操作
void action1() {
printf("Performing action 1.\n");
}
void action2() {
printf("Performing action 2.\n");
}
int main() {
/*状态和事件初始化*/
State current_state = State_A;
Event current_event = Event_1;
/*查找状态转换,并执行相应的操作*/
Transition* transition = findTransition(current_state, current_event);
if (transition != NULL) {
/*如果表中存在对应的数据,则更新状当前状态*/
current_state = transition->next_state;
/*执行转换动作*/
transition->action();
}
return 0;
}
三、状态模式
回主目录
使用面向对象的方式,将状态抽象为类,但在C语言中,并不能直接使用面向对象的语法来实现状态机。但是可以通过结构体和函数指针来模拟面向对象的思想,如下所示:
#include <stdio.h>
// 定义状态机结构体
typedef struct {
void (*state)();
void (*transition)(Event);
} StateMachine;
// 定义状态函数
void stateA(Event event);
void stateB(Event event);
void stateC(Event event);
// 定义状态机对象
StateMachine state_machine = {stateA, NULL};
// 定义状态转换函数
void transition(Event event)
{
state_machine.state(event);
}
// 定义状态函数的实现
void stateA(Event event)
{
if (event == Event_1)
{
printf("Performing action 1.\n");
state_machine.state = stateB;
}
else if (event == Event_2)
{
printf("Performing action 2.\n");
state_machine.state = stateC;
}
}
void stateB(Event event)
{
// 状态B的实现...
}
void stateC(Event event)
{
// 状态C的实现...
}
int main()
{
Event current_event = Event_1;
// 执行状态转换
transition(current_event);
return 0;
}
总结:以上就是状态机的一些内容,它可以说是一种总结归纳的思想,能让你更好的梳理整个系统的逻辑。