EMS 知识库
首页 / knowledge/代码解析/hmi/led

led_dev.h

源文件路径:hmi/led/led_dev.h 所属模块:hmi/led(人机界面 - WS2812 灯带编码/驱动层) 代码行数:87

1. 文件职责

本文件是 WS2812 灯带编码/驱动层的头文件,定义灯带规格(颗数、每颗 bit 数、DMA 缓冲大小)、时序脉冲常量(T0_PULSE/T1_PULSE)、读写互斥标志联合体 WS2812_FLAG_U,并声明 5 个驱动函数与 2 个全局对象。

它处在灯带数据流的最底层入口:上层 hmi/led/app_led.c 通过 ws2812_set_color_hex() 逐颗写入编码缓冲,通过 ws2812_update() 触发一次 DMA 发送;中断侧 hardware/dma/dma.c:266-283(DMA0_Channel0_IRQHandler)通过 g_u_ws2812_flag.bit.write_flag 与本层做握手。

本层不做业务判断,也不直接操作定时器/GPIO 寄存器(那些在 hardware/timer/timer4.c、hardware/dma/dma.c 中),它只负责把颜色转换成"每 bit 一个比较值"的 32 位数组。

被谁驱动:system/board_init/board_init.c:242 在上电初始化阶段调用 ws2812_init();之后的 ws2812_update() 只可能由 hmi/led/app_led.c:207 的 led_build_full_buffer() 调用(当前该调用链未接线)。

2. 关键数据结构与宏

名称类型(结构体/枚举/宏/联合体)说明
__LED_DEV_H__宏(防重包含)头文件保护宏,hmi/led/led_dev.h:9-10
LED_LONG_NUM宏(= 101)长灯带(系统状态指示灯)灯珠数,hmi/led/led_dev.h:21。注释说明:绿=正常、红=故障、黄=告警、灭=未运行
LED_SOC_NUM宏(= 20)短灯带(SOC 灯显)灯珠数,hmi/led/led_dev.h:27。注释写"精度为10%、左侧 0%、右侧 100%、白=联网、蓝=未联网"
RKP_LED_NUM宏(= LED_LONG_NUM + LED_SOC_NUM = 121)灯珠总数,hmi/led/led_dev.h:32。注释残留 //最终39,与实际 121 不符
LED_BITS宏(= 24)每颗灯珠的数据位数(GRB 各 8 bit),hmi/led/led_dev.h:33
LED_BUFFER_SIZE宏(= RKP_LED_NUM * LED_BITS = 2904)DMA 缓冲区表项数,hmi/led/led_dev.h:34
T0_PULSE宏(#if 1 分支 = 54)WS2812 数据"0"对应的定时器比较值,hmi/led/led_dev.h:38。注释:0.32/0.00595 ≈ 53.7 个周期
T1_PULSE宏(#if 1 分支 = 134)数据"1"对应的比较值,hmi/led/led_dev.h:39。注释:0.67/0.00595 ≈ 112.6(注释与取值不一致,取值 134)
T0_PULSE/T1_PULSE(#else 分支)宏(54/134 互换)针对"取反"极性的备选取值,hmi/led/led_dev.h:43-44,当前被 #if 1 屏蔽
WS2812_FLAG_U联合体(hmi/led/led_dev.h:52-67)读写互斥标志:u8 u8_all 与位域 bit{ read_flag:1; write_flag:1; soc_color_flag:1; net_color_flag:1; sys_run_color_flag:1; reserve:3; }。本层实际只用前两位
g_u16_ws2812_data全局数组声明(u32[LED_BUFFER_SIZE + 3],hmi/led/led_dev.h:72)DMA 编码缓冲,定义于 hmi/led/led_dev.c:61,用 __attribute__((at(SDRAM_WS2812_DATA_ADDR))) 固定到 SDRAM。多出的 3 个表项用于帧尾附加周期
g_u_ws2812_flag全局变量声明(volatile WS2812_FLAG_U,hmi/led/led_dev.h:73)任务/中断共用的读写标志,定义于 hmi/led/led_dev.c:62

3. 函数清单

本文件只有函数声明,没有任何函数定义。括号内为对应实现在 hmi/led/led_dev.c 的行号。

函数名作用域(static/全局)说明(一句话)
ws2812_init全局(声明 hmi/led/led_dev.h:79,定义 led_dev.c:72)初始化 TIMER4 的 800 kHz PWM 与 DMA0 通道 0,并清零编码缓冲
ws2812_update全局(声明 hmi/led/led_dev.h:80,定义 led_dev.c:86)等待写缓冲空闲后,把 PA3 切回复用功能、使能 DMA 与定时器,启动一次帧发送
ws2812_set_color_rgb全局(声明 hmi/led/led_dev.h:81,定义 led_dev.c:101)以 R/G/B 三通道参数写入第 led_idx 颗灯珠的 24 bit 编码(RGB 顺序,无 GRB 转换,全工程无调用点)
ws2812_set_color_hex全局(声明 hmi/led/led_dev.h:82,定义 led_dev.c:118)以 0xRRGGBB 写入第 led_idx 颗灯珠,内部转换成 GRB 顺序后逐 bit 编码
ws2812_set_color_buffer_clear全局(声明 hmi/led/led_dev.h:83,定义 led_dev.c:153)把全部 RKP_LED_NUM 颗灯珠颜色清零(依赖 ws2812_set_color_hex 实现)

注:hmi/led/led_dev.c:170 还定义了一个未在本头文件声明的函数 ws2812_set_on_off_color_light(u8, u32),见 hmi/led/led_dev.c.md。

4. 核心逻辑解析

本文件是纯声明头,无逻辑。它定义的常量决定了整条灯带的运行参数,推导如下:

4.1 缓冲与帧长

4.2 位编码方式

T0_PULSE/T1_PULSE 是定时器比较寄存器的加载值,不是电平宽度本身:

宏值注释中的对应时间换算(1 计数 = 1/168 MHz = 5.95 ns)
T0_PULSE540.32 µs54 × 5.95 ns ≈ 0.321 µs
T1_PULSE134注释写 0.67 µs(并附 (112) 备选)134 × 5.95 ns ≈ 0.797 µs

hardware/timer/timer4.c:59 把通道 3 配置为 TIMER_OC_POLARITY_LOW(反相输出),而本头文件当前生效的却是标注 //不取反 的 #if 1 分支(hmi/led/led_dev.h:36-39)。两者对"取反/不取反"的标注互相矛盾,属于现场调参遗留(见第 7 节)。

4.3 读写互斥标志 WS2812_FLAG_U

位名称写入方读取方语义
bit0read_flagws2812_set_color_hex()/ws2812_set_color_rgb() 置 1 与清 0(hmi/led/led_dev.c:109/114)ws2812_update() 自旋等待(led_dev.c:88)"正在修改内存缓冲"
bit1write_flagws2812_update() 置 1(led_dev.c:92);DMA0_Channel0_IRQHandler 清 0(hardware/dma/dma.c:280)全部写函数开头检查(led_dev.c:103/121/155/174)"DMA 正在发送,禁止改缓冲"
bit2-4soc_color_flag/net_color_flag/sys_run_color_flag无无预留,未使用;reserve:3 补齐 8 位

由于 u8_all 与位域共用同一字节,置位/清位都是对同一字节的读-改-写,任务上下文与 DMA 中断上下文之间没有关中断保护,存在标志丢失的可能(详见第 7 节)。

4.4 与 uCOS-II / 中断的配合

5. 对外接口

本文件导出

名称类型使用方
ws2812_init函数声明system/board_init/board_init.c:242
ws2812_update函数声明hmi/led/app_led.c:207
ws2812_set_color_hex函数声明hmi/led/app_led.c:191、201(生效分支)与 169、173(#if 0 分支内)、hmi/led/led_dev.c:160、190
ws2812_set_color_buffer_clear函数声明hmi/led/app_led.c:160
ws2812_set_color_rgb函数声明无调用点
g_u16_ws2812_data全局数组声明hardware/dma/dma.c:53/55(DMA 源地址与长度)、hmi/led/led_dev.c:76
g_u_ws2812_flag全局变量声明hardware/dma/dma.c:280(中断清 write_flag)、hmi/led/led_dev.c 全部函数
LED_LONG_NUM/LED_SOC_NUM/RKP_LED_NUM/LED_BITS/LED_BUFFER_SIZE/T0_PULSE/T1_PULSE/WS2812_FLAG_U宏/类型hmi/led/led_dev.c、hmi/led/app_led.c(仅 LED_SOC_NUM、RKP_LED_NUM);hardware/dma/dma.h:17 通过 include 间接可见

本文件调用的外部函数/变量:无(纯声明头)。其 #include "chip.h"、"sdram.h" 分别提供 u8/u16/u32 类型与 SDRAM_WS2812_DATA_ADDR 地址宏。

6. 依赖关系

7. 备注与风险点