文章目录
- 前言
- 一、LED 显示框架概述
- 1. 框架结构图
- 2. 基本机制
- 二、核心结构与接口设计
- 1. 状态命令结构
- 2. 状态项结构
- 3. LED框架配置结构
- 4. LED运行控制器
- 三、LED框架逻辑流程
- 1. 初始化逻辑
- 2. 优先级抢占判断与处理逻辑
- 3. 执行队列命令并处理tick
- 4. 队列为空时的默认状态回滚
- 四、LED状态模块封装样例
- 1. 颜色定义与显示
- 2. 定义状态项数组与配置
- 五、框架使用接口
- 六、总结与展望
前言
在嵌入式系统中,RGB LED状态指示常用于设备运行状态、故障信息或工作模式的直观提示。在多个状态同时存在的情况下,我们希望能让更紧急或重要的状态信息抢占当前的LED显示内容,同时又能保留各状态的独立性和易于扩展的逻辑。
本文将详细解析该LED显示框架的设计思路、核心组件及其实现方式,并对关键代码进行深入剖析,帮助读者理解如何在嵌入式系统中高效地管理LED状态显示。它具有以下核心特性:
-
✅ 支持多个状态模块
-
✅ 支持不同状态的优先级判断
-
✅ 状态判断函数独立,便于维护
-
✅ 状态优先级支持抢占式切换
-
✅ 同一优先级的状态为先进先出
-
✅ 支持插队队列管理显示时序
一、LED 显示框架概述
该LED显示框架的设计目标是实现对LED状态的智能化管理,具体包括:
-
任务优先级管理:不同的LED状态具有不同的优先级,高优先级的状态可以抢占低优先级的状态显示。
-
队列机制:同一优先级的状态按照先进先出的原则进行显示,确保状态切换的有序性。
-
模块化设计:将LED状态的检测、插入、执行等功能模块化,提升代码的可读性和可维护性。
1. 框架结构图
+---------------------------+
| led_arch_t 控制器 |
+---------------------------+
| config 配置结构体 |
| cmd_queue 指令队列 |
| cur_led_id 当前状态ID |
| tick 计数器 |
+---------------------------+|| 调用周期函数v
+---------------------------+
| led_on_tick() |
+---------------------------+|| 查询各状态check函数(按优先级)v
+---------------------------+
| 判断是否抢占并更新状态 |
+---------------------------+|| 出队并执行 color_exec()v
+---------------------------+
| LED 实际颜色控制逻辑 |
+---------------------------+
2. 基本机制
-
每个LED状态模块对应一个 led_arch_t 实例;
-
每个状态定义一个 led_item_t,包含状态ID、优先级、检测函数;
-
led_cmd_t 用于表示某一颜色状态及持续时长;
-
状态变化以命令队列形式插入,每周期执行一个命令;
-
高优先级状态抢占低优先级状态,并清空其未执行完的命令;
-
同一优先级状态不会抢占,而是先进先出轮流执行。
二、核心结构与接口设计
1. 状态命令结构
typedef struct {uint8_t color; // 颜色枚举值uint8_t ticks; // 显示该颜色的周期数
} led_cmd_t;
每条命令定义一种颜色在一定时间内保持显示。
2. 状态项结构
typedef struct {uint16_t id; // 状态 IDuint8_t prio; // 优先级,值越小优先级越高bool_t (*led_sta_check)(void); // 检查函数,判断当前状态是否激活
} led_item_t;
每种状态都可配置一个 check 函数,若返回 true 表示状态应被激活。
3. LED框架配置结构
typedef struct {char *name; // 名称led_cmd_t *cmd_buf; // 命令缓冲区(循环队列)uint16_t cmd_buf_size; // 命令缓冲区大小const led_item_t *led_item; // 所有状态定义数组const uint16_t led_item_num;// 状态总数void (*color_exec)(uint8_t color); // 执行颜色显示函数
} led_arch_config_t;
4. LED运行控制器
typedef struct {const led_arch_config_t *config;ring_queue_t cmd_queue; // 实际的命令队列结构(环形队列)uint32_t tick; // 当前命令已经执行的tick数uint16_t cur_led_id; // 当前正在运行的状态IDuint8_t init_flag; // 是否已经初始化
} led_arch_t;
三、LED框架逻辑流程
1. 初始化逻辑
if(p->init_flag == 0)
{p->init_flag = 1;init_queue(&p->cmd_queue, NULL, p->config->cmd_buf_size);p->tick = 0;p->cur_led_id = LED_STA_ID_DEFAULT;if(p->config->led_item[LED_ID_INIT].led_sta_check){p->cur_led_id = LED_ID_INIT;p->config->led_item[LED_ID_INIT].led_sta_check();}
}
首次调用 led_on_tick() 时自动初始化,并调用 INIT 状态的 check 函数插入初始命令。
2. 优先级抢占判断与处理逻辑
for(uint16_t id=(LED_ID_INIT+1); id<p->config->led_item_num; ++id)
{if(p->config->led_item[id].prio < p->config->led_item[p->cur_led_id].prio){if(p->config->led_item[id].led_sta_check && p->config->led_item[id].led_sta_check()){// 抢占当前低优先级状态for(uint16_t i=0; i<queue_length(&p->cmd_queue); ++i)rdIdx_add(&p->cmd_queue); // 清空现有命令p->cur_led_id = id; // 切换当前状态break;}}else break;
}
-
只检测优先级更高的状态
-
如果检测为真,则清除命令队列,实现抢占
-
切换当前状态ID
3. 执行队列命令并处理tick
if(queue_empty(&p->cmd_queue) == FALSE)
{uint16_t rdIdx = get_queue_rdIdx_index(&p->cmd_queue);p->config->color_exec(p->config->cmd_buf[rdIdx].color);++p->tick;if(p->tick >= p->config->cmd_buf[rdIdx].ticks){rdIdx_add(&p->cmd_queue);p->tick = 0;}
}
每次 tick 调用:
-
从队头读取一条命令
-
调用 color_exec 真实点灯
-
达到tick数后出队
4. 队列为空时的默认状态回滚
else
{if (p->config->led_item[p->cur_led_id].led_sta_check() != TRUE){p->cur_led_id = p->config->led_item_num - 1; // 默认态for(uint16_t id=(LED_ID_INIT+1); id<p->config->led_item_num; ++id) {if(p->config->led_item[id].led_sta_check && p->config->led_item[id].led_sta_check()){p->cur_led_id = id;break;}}}
}
若当前状态失效且队列为空,回退到默认状态。
四、LED状态模块封装样例
1. 颜色定义与显示
typedef enum {LED_OFF,LED_RED,LED_GREEN,LED_BLUE,LED_YELLOW,LED_WHITE,
} color_t;void sta_led_color_exec(uint8_t color)
{switch(color){case LED_RED: LED_show(RED); break;case LED_GREEN: LED_show(GREEN); break;case LED_BLUE: LED_show(BLUE); break;case LED_YELLOW:LED_show(YELLOW); break;case LED_WHITE: LED_show(WHITE); break;case LED_OFF: LED_show(0); break;default: break;}
}
2. 定义状态项数组与配置
const static led_item_t led_sta_item[] = {{LED_INIT, 0, led_init},{LED_TASK1, 1, led_task1},{LED_TASK2, 2, led_task2},{LED_TASK3, 3, led_task3},{LED_TASK4, 4, led_task4},
};const static led_arch_config_t led_sta_config = {.name = "sys sta led",.cmd_buf = led_sta_cmd_buf,.cmd_buf_size = 16,.led_item = led_sta_item,.led_item_num = sizeof(led_sta_item) / sizeof(led_item_t),.color_exec = sta_led_color_exec,
};static led_arch_t led_sta_arch = {.config = &led_sta_config,
};
五、框架使用接口
void led_sta_on_tick(void)
{led_on_tick(&led_sta_arch); // 每周期调用
}void led_sta_clean(void)
{led_on_clean(&led_sta_arch); // 清除命令
}
六、总结与展望
本框架结合优先级调度、命令队列、颜色执行解耦等技术手段,构建了一个灵活而强大的LED指示灯状态控制方案。其特点如下:
-
支持多个状态同时注册;
-
通过优先级实现紧急状态的插队处理;
-
支持FIFO队列展示同优先级下的多个状态指示;
-
支持动态插入状态指令,适应复杂系统场景;
-
框架通用,可在多个产品中复用。
后续可扩展功能包括:
-
状态时间动态可调;
-
LED闪烁模式定义;
-
多灯协同控制(如多个LED协同构成特定图案);
-
低功耗模式下的灯效优化等。