文章目錄
- 前言
- 一、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協同構成特定圖案);
-
低功耗模式下的燈效優化等。