C语言实现嵌入式状态机简单描述与应用

简介: C语言实现嵌入式状态机简单描述与应用

说明

嵌入式状态机是一种常用的软件设计模式,它能够提高代码的可读性和可维护性。状态机是一个抽象的概念,它描述了一个系统或者组件的不同状态以及在不同状态下如何响应输入和事件。状态机可以应用于各种领域,比如通信协议、嵌入式系统、控制系统等。

在C语言中,可以使用有限状态机(FSM)实现嵌入式状态机。有限状态机可以通过一组状态和状态之间的转换来描述系统或者组件的行为。在嵌入式系统中,通常使用循环或者中断处理程序来实现状态机

当系统需要执行某个任务时,可以根据状态机的状态选择不同的操作,例如:

  • 控制系统状态:例如控制器根据状态机的状态选择执行不同的操作,从而控制整个系统的状态,例如开关灯、控制电机等。
  • 系统调度:例如操作系统根据状态机的状态选择执行不同的任务,从而实现系统的调度。
  • 系统事件处理:例如网络通信系统根据状态机的状态选择不同的数据处理方式,例如处理接收到的数据、发送数据等。
  • 系统错误处理:例如系统出现错误时,可以根据状态机的状态选择不同的错误处理方式,例如重新启动系统、输出错误信息等。

总之,状态机可以帮助我们将系统的复杂性分解为多个简单的状态,根据不同的状态选择执行不同的操作,从而更好地实现系统的设计与开发。

主要流程

  1. 定义状态和事件
    首先需要定义系统可能存在的所有状态,通常用枚举类型来表示。同时需要定义可能发生的所有事件,例如输入的数据、定时器到达等。
  2. 初始化状态机
    在程序启动时,需要将状态机初始化为特定的状态。
  3. 定义状态转换和动作
    使用switch-case if-else 函数指针等语句来定义状态转换和动作。当事件发生时,判断当前状态,并根据不同的事件执行相应的动作,并将状态转换为下一个状态。
  4. 事件处理
    当有事件发生时,将事件作为参数传递给状态机,并调用状态转换和动作函数。
  5. 循环执行
    状态机通常作为一个独立的任务运行,并在一个无限循环中等待事件的发生。

举例

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}

当然实现状态机的方式并不是惟一的。

相关文章
|
1月前
|
存储 算法 C语言
通义灵码在考研C语言和数据结构中的应用实践 1-5
通义灵码在考研C语言和数据结构中的应用实践,体验通义灵码的强大思路。《趣学C语言和数据结构100例》精选了五个经典问题及其解决方案,包括求最大公约数和最小公倍数、统计字符类型、求特殊数列和、计算阶乘和双阶乘、以及求斐波那契数列的前20项和。通过这些实例,帮助读者掌握C语言的基本语法和常用算法,提升编程能力。
67 4
|
1月前
|
C语言
链式栈实现(C语言描述)
这篇文章介绍了如何在C语言中实现链式栈,包括节点和栈的创建、入栈、出栈、获取栈顶元素、判断栈是否为空以及销毁栈的操作。
23 1
|
1月前
|
C语言
数组栈的实现(C语言描述)
本文介绍了如何在C语言中使用数组来实现栈的数据结构,包括栈的创建、入栈、出栈、获取栈顶元素、检查栈是否为空、获取栈的大小以及销毁栈等操作,并提供了相应的函数实现。
33 1
|
1月前
|
C语言
链式顺序表实现(C语言描述)
本文介绍了如何在C语言中实现链式顺序表,包括数据结构的定义、节点的创建、数据的插入和删除以及链表的打印和销毁。
39 2
|
1月前
|
C语言
顺序表数组法构建(C语言描述)
如何使用C语言通过数组方法构建有序顺序表,包括顺序表的创建、插入、删除和打印等。
20 2
|
1月前
|
C语言
无头链表再封装方式实现 (C语言描述)
如何在C语言中实现无头链表的再封装,包括创建节点和链表、插入和删除操作、查找和打印链表以及销毁链表的函数。
27 0
ly~
|
1月前
|
网络协议 算法 关系型数据库
C语言的应用
C 语言因其高效性和对硬件的直接访问能力,在多个领域有广泛应用。在系统软件领域,它被用于开发操作系统(如 Unix 和 Linux 的内核)和嵌入式系统(如汽车电子控制系统)。在游戏开发中,C 语言常用于构建游戏引擎的底层部分(如 Unity 和 Unreal Engine 的核心模块)及性能要求高的独立游戏。此外,C 语言也用于数据库管理系统(如 MySQL 和 PostgreSQL 的核心功能)和网络编程(如 TCP/IP 协议栈和网络服务器的核心模块)。
ly~
36 3
|
1月前
|
Java Unix Linux
1.3 C语言的应用范围
C语言自20世纪80年代以来一直是主流编程语言,适用于小型计算机、个人电脑及大型机。因其高效紧凑且易于修改和移植,广泛用于软件开发。尽管后来C++和JAVA流行起来,但C语言仍然是软件行业核心,并在嵌入式系统、科学编程和操作系统开发如Linux中扮演重要角色。即使到现在,掌握C语言仍是一项重要技能。不是必须得是计算机专家才能使用C语言,学习C语言同时也能学到很多C++的知识。
50 8
|
1月前
|
C语言
无头链表二级指针方式实现(C语言描述)
本文介绍了如何在C语言中使用二级指针实现无头链表,并提供了创建节点、插入、删除、查找、销毁链表等操作的函数实现,以及一个示例程序来演示这些操作。
27 0
|
2月前
|
存储 C语言
数据结构基础详解(C语言): 树与二叉树的应用_哈夫曼树与哈夫曼曼编码_并查集_二叉排序树_平衡二叉树
本文详细介绍了树与二叉树的应用,涵盖哈夫曼树与哈夫曼编码、并查集以及二叉排序树等内容。首先讲解了哈夫曼树的构造方法及其在数据压缩中的应用;接着介绍了并查集的基本概念、存储结构及优化方法;随后探讨了二叉排序树的定义、查找、插入和删除操作;最后阐述了平衡二叉树的概念及其在保证树平衡状态下的插入和删除操作。通过本文,读者可以全面了解树与二叉树在实际问题中的应用技巧和优化策略。
下一篇
无影云桌面