说明
嵌入式状态机是一种常用的软件设计模式,它能够提高代码的可读性和可维护性。状态机是一个抽象的概念,它描述了一个系统或者组件的不同状态以及在不同状态下如何响应输入和事件。状态机可以应用于各种领域,比如通信协议、嵌入式系统、控制系统等。
在C语言中,可以使用有限状态机(FSM)实现嵌入式状态机。有限状态机可以通过一组状态和状态之间的转换来描述系统或者组件的行为。在嵌入式系统中,通常使用循环或者中断处理程序来实现状态机
当系统需要执行某个任务时,可以根据状态机的状态选择不同的操作,例如:
- 控制系统状态:例如控制器根据状态机的状态选择执行不同的操作,从而控制整个系统的状态,例如开关灯、控制电机等。
- 系统调度:例如操作系统根据状态机的状态选择执行不同的任务,从而实现系统的调度。
- 系统事件处理:例如网络通信系统根据状态机的状态选择不同的数据处理方式,例如处理接收到的数据、发送数据等。
- 系统错误处理:例如系统出现错误时,可以根据状态机的状态选择不同的错误处理方式,例如重新启动系统、输出错误信息等。
总之,状态机可以帮助我们将系统的复杂性分解为多个简单的状态,根据不同的状态选择执行不同的操作,从而更好地实现系统的设计与开发。
主要流程
- 定义状态和事件
首先需要定义系统可能存在的所有状态,通常用枚举类型来表示。同时需要定义可能发生的所有事件,例如输入的数据、定时器到达等。 - 初始化状态机
在程序启动时,需要将状态机初始化为特定的状态。 - 定义状态转换和动作
使用switch-case if-else 函数指针等语句来定义状态转换和动作。当事件发生时,判断当前状态,并根据不同的事件执行相应的动作,并将状态转换为下一个状态。 - 事件处理
当有事件发生时,将事件作为参数传递给状态机,并调用状态转换和动作函数。 - 循环执行
状态机通常作为一个独立的任务运行,并在一个无限循环中等待事件的发生。
举例
1#include <stdio.h> 2 3// 定义状态机的所有可能状态 4enum { 5 STATE_IDLE, 6 STATE_RUNNING, 7 STATE_COMPLETE, 8 NUM_STATES 9}; 10 11// 定义状态机的事件类型 12enum { 13 EVENT_START, 14 EVENT_STOP, 15 NUM_EVENTS 16}; 17 18// 定义状态机的数据结构 19typedef struct { 20 int current_state; 21 void (*process_event)(int event); 22} state_machine_t; 23 24// 定义状态机的处理函数 25void idle_state(int event) { 26 if (event == EVENT_START) { 27 printf("Idle state: starting...\n"); 28 // 将状态机的当前状态改为运行状态 29 state_machine.current_state = STATE_RUNNING; 30 } 31} 32 33void running_state(int event) { 34 if (event == EVENT_STOP) { 35 printf("Running state: stopping...\n"); 36 // 将状态机的当前状态改为完成状态 37 state_machine.current_state = STATE_COMPLETE; 38 } 39} 40 41void complete_state(int event) { 42 printf("Complete state: done.\n"); 43} 44 45// 初始化状态机 46state_machine_t state_machine = { 47 .current_state = STATE_IDLE, 48 .process_event = idle_state 49}; 50 51int main() { 52 // 在循环中读取事件并将其传递给状态机 53 while (1) { 54 int event; 55 scanf("%d", &event); 56 state_machine.process_event(event); 57 if (state_machine.current_state == STATE_COMPLETE) { 58 break; 59 } 60 } 61 return 0; 62}
在上面的例子中,我们定义了三个状态:空闲状态、运行状态和完成状态。我们还定义了两个事件:启动事件和停止事件。状态机的数据结构包含当前状态和处理当前状态的函数的指针。我们还定义了三个处理函数,分别处理空闲状态、运行状态和完成状态。在处理函数中,我们根据当前状态和事件决定下一个状态以及执行相应的操作。在应用程序中,我们初始化状态机,然后在循环中读取事件并将其进行传递。
事例二
1// 定义状态枚举值 2typedef enum { 3 STATE_OFF, 4 STATE_ON 5} led_state_t; 6 7// 定义状态机结构体 8typedef struct { 9 led_state_t state; // 当前状态 10 void (*turn_on)(); // 执行开启操作的函数指针 11 void (*turn_off)(); // 执行关闭操作的函数指针 12} led_fsm_t; 13 14// 初始化状态机 15void led_fsm_init(led_fsm_t* fsm, void (*turn_on)(), void (*turn_off)()) { 16 fsm->state = STATE_OFF; 17 fsm->turn_on = turn_on; 18 fsm->turn_off = turn_off; 19} 20 21// 状态机的状态转换 22void led_fsm_transition(led_fsm_t* fsm, bool button_pressed) { 23 switch (fsm->state) { 24 case STATE_OFF: 25 if (button_pressed) { 26 fsm->state = STATE_ON; 27 fsm->turn_on(); 28 } 29 break; 30 case STATE_ON: 31 if (button_pressed) { 32 fsm->state = STATE_OFF; 33 fsm->turn_off(); 34 } 35 break; 36 default: 37 break; 38 } 39} 40 41// 主函数 42int main() { 43 // 定义LED状态机 44 led_fsm_t led_fsm; 45 // 初始化状态机 46 led_fsm_init(&led_fsm, turn_on_led, turn_off_led); 47 while (1) { 48 // 读取输入 49 bool button_pressed = read_button(); 50 // 状态机的状态转换 51 led_fsm_transition(&led_fsm, button_pressed); 52 // 等待下一次执行 53 delay(10); 54 } 55 return 0; 56}
示例3
1/*举类型state_t,其中包含四个状态:IDLE、WAITING、RUNNING和STOPPED。*/ 2typedef enum { 3 STATE_IDLE, 4 STATE_WALKING, 5 STATE_TURNING_LEFT, 6 STATE_TURNING_RIGHT, 7 STATE_STOPPED 8} robot_state_t; 9 10void transition_fn(void); 11/*用于存储当前状态和状态转移规则*/ 12typedef struct { 13 robot_state_t current_state; 14 void (*transition_fn)(void); 15} robot_t; 16 17robot_t robot; 18 19int main(void) { 20 // initialize robot 21 robot.current_state = STATE_IDLE; 22 robot.transition_fn = transition_fn; 23 24 // main loop 25 while (1) { 26 switch (robot.current_state) { 27 case STATE_IDLE: 28 // do nothing 29 break; 30 case STATE_WALKING: 31 // move robot forward 32 break; 33 case STATE_TURNING_LEFT: 34 // turn robot left 35 break; 36 case STATE_TURNING_RIGHT: 37 // turn robot right 38 break; 39 case STATE_STOPPED: 40 // stop robot 41 break; 42 } 43 } 44} 45 46void transition_fn(void) { 47 switch (robot.current_state) { 48 case STATE_IDLE: 49 // transition to STATE_WALKING 50 robot.current_state = STATE_WALKING; 51 break; 52 case STATE_WALKING: 53 // transition to STATE_TURNING_LEFT or STATE_TURNING_RIGHT or STATE_STOPPED 54 if (/* condition for turning left */) { 55 robot.current_state = STATE_TURNING_LEFT; 56 } else if (/* condition for turning right */) { 57 robot.current_state = STATE_TURNING_RIGHT; 58 } else if (/* condition for stopping */) { 59 robot.current_state = STATE_STOPPED; 60 } 61 break; 62 case STATE_TURNING_LEFT: 63 // transition to STATE_WALKING 64 robot.current_state = STATE_WALKING; 65 break; 66 case STATE_TURNING_RIGHT: 67 // transition to STATE_WALKING 68 robot.current_state = STATE_WALKING; 69 break; 70 case STATE_STOPPED: 71 // transition to STATE_IDLE 72 robot.current_state = STATE_IDLE; 73 break; 74 } 75}
当然实现状态机的方式并不是惟一的。