-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathARGB.h
More file actions
274 lines (235 loc) · 8.21 KB
/
Copy pathARGB.h
File metadata and controls
274 lines (235 loc) · 8.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
/**
*******************************************
* @file ARGB.h
* @author Dmitriy Semenov / Crazy_Geeks
* @link https://crazygeeks.ru
* @version 3.00
* @date 06-Oct-2025
* @brief ARGB驱动头文件(可寻址RGB LED)
* @note 针对多条独立配置的LED灯带进行优化
* @note 仓库: https://github.com/Crazy-Geeks/STM32-ARGB-DMA
*******************************************
*/
#ifndef ARGB_H_
#define ARGB_H_
#include "stdint.h"
#include "tim.h"
/**
* @brief RGB颜色结构体
*/
typedef struct {
uint8_t r; ///< 红色分量
uint8_t g; ///< 绿色分量
uint8_t b; ///< 蓝色分量
} ARGB_RGB;
/**
* @brief HSV颜色结构体
*/
typedef struct {
uint8_t h; ///< 色调
uint8_t s; ///< 饱和度
uint8_t v; ///< 明度
} ARGB_HSV;
/**
* @brief 获取DMA元素大小(字节数)
*/
#define ARGB_DMA_ELEM_SIZE(dma_size) \
((dma_size) == ARGB_DMA_WORD ? sizeof(uint32_t) \
: (dma_size) == ARGB_DMA_HWORD ? sizeof(uint16_t) \
: sizeof(uint8_t))
// #define ARGB_USE_DYNAMIC_BUFFERS
#ifdef ARGB_USE_DYNAMIC_BUFFERS
// 使用动态分配的缓冲区
typedef void *(*ARGB_Malloc)(size_t size);
typedef void (*ARGB_Free)(void *ptr);
#else
// 使用静态分配的缓冲区
/**
* @brief 获取每个像素的字节数
*/
#define ARGB_BYTES_PER_PIXEL(led_type) ((led_type) == ARGB_SK6812 ? 4 : 3)
/**
* @brief 计算RGB缓冲区大小
* @param num_pixels 像素数量
* @param led_type LED类型
*/
#define ARGB_GET_RGB_BUF_SIZE(num_pixels, led_type) \
((num_pixels) * ARGB_BYTES_PER_PIXEL(led_type))
/**
* @brief 计算PWM缓冲区大小
* @param dma_size DMA传输大小
* @param led_type LED类型
*/
#define ARGB_GET_PWM_BUF_SIZE(dma_size, led_type) \
(ARGB_BYTES_PER_PIXEL(led_type) * 8 * 2 * ARGB_DMA_ELEM_SIZE(dma_size))
#endif
/**
* @addtogroup ARGB_Driver
* @brief 可寻址RGB LED驱动
* @{
*/
/**
* @enum ARGB_STATE
* @brief 驱动状态枚举
*/
typedef enum {
ARGB_BUSY = 0, ///< DMA传输正在进行
ARGB_READY = 1, ///< DMA准备就绪可以传输
ARGB_OK = 2, ///< 函数执行成功
ARGB_PARAM_ERR = 3, ///< 输入参数错误
ARGB_MEM_ERR = 4 ///< 内存分配错误
} ARGB_STATE;
/**
* @enum ARGB_LED_TYPE
* @brief LED类型枚举
*/
typedef enum {
ARGB_WS2811S = 0, ///< RGB顺序, 400kHz
ARGB_WS2811F = 1, ///< RGB顺序, 800kHz
ARGB_WS2812 = 2, ///< GRB顺序, 800kHz
ARGB_SK6812 = 3 ///< RGBW顺序, 800kHz (带白光通道)
} ARGB_LED_TYPE;
/**
* @enum ARGB_DMA_SIZE
* @brief DMA内存数据宽度
*/
typedef enum {
ARGB_DMA_BYTE = 0, ///< 8位传输
ARGB_DMA_HWORD = 1, ///< 16位传输
ARGB_DMA_WORD = 2 ///< 32位传输
} ARGB_DMA_SIZE;
/**
* @brief ARGB LED灯带句柄结构体
* @note 每个实例代表一条具有独立配置的LED灯带
*/
typedef struct ARGB_HandleTypeDef {
// 硬件句柄
TIM_HandleTypeDef *htim; ///< 定时器句柄指针
DMA_HandleTypeDef *hdma; ///< DMA句柄指针
uint32_t tim_channel; ///< 定时器PWM通道
// 缓存的定时器/DMA参数(初始化时计算一次)
uint32_t dma_id; ///< 定时器DMA ID (TIM_DMA_ID_CCx)
uint32_t dma_cc; ///< 定时器DMA CC标志 (TIM_DMA_CCx)
volatile uint32_t *ccr_addr; ///< CCR寄存器地址
// 配置参数
ARGB_LED_TYPE led_type; ///< LED灯带类型
ARGB_DMA_SIZE dma_size; ///< DMA传输大小
uint16_t num_pixels; ///< 此灯带的像素数量
uint8_t use_gamma; ///< 伽马校正标志 (0或1)
// PWM时序值
volatile uint8_t pwm_hi; ///< PWM高电平脉宽(逻辑1)
volatile uint8_t pwm_lo; ///< PWM低电平脉宽(逻辑0)
// 状态参数
volatile uint8_t brightness; ///< LED全局亮度 [0..255]
volatile ARGB_STATE state; ///< 缓冲区发送状态
volatile uint16_t buf_counter; ///< PWM缓冲区迭代器
// 动态缓冲区
volatile uint8_t *rgb_buf; ///< LED颜色数据缓冲区(RGB/RGBW数据)
volatile void *pwm_buf; ///< 定时器PWM值缓冲区(类型取决于dma_size)
// 缓冲区大小(初始化时计算)
uint16_t rgb_buf_size; ///< RGB缓冲区字节大小
uint16_t pwm_buf_len; ///< PWM缓冲区长度
uint8_t bytes_per_pixel; ///< 每像素字节数(RGB为3,RGBW为4)
#ifdef ARGB_USE_DYNAMIC_BUFFERS
ARGB_Malloc malloc; ///< 内存分配函数指针
ARGB_Free free; ///< 内存释放函数指针
#endif
struct ARGB_HandleTypeDef *next; ///< 链表中的下一个实例
} ARGB_HandleTypeDef;
// 初始化和控制函数
/**
* @brief 初始化LED灯带
* @param[in] hargb ARGB句柄指针
* @param[in] htim 定时器句柄指针
* @param[in] hdma DMA句柄指针
* @param[in] tim_channel 定时器通道 (TIM_CHANNEL_1/2/3/4)
* @param[in] num_pixels 灯带中的像素数量
* @param[in] led_type LED灯带类型
* @param[in] dma_size DMA传输大小
* @param[in] use_gamma 启用伽马校正 (0或1)
* @param[in] rgb_buf RGB缓冲区指针(静态模式)
* @param[in] pwm_buf PWM缓冲区指针(静态模式)
* @return ARGB_STATE 状态
*/
ARGB_STATE ARGB_Init(ARGB_HandleTypeDef *hargb, TIM_HandleTypeDef *htim,
DMA_HandleTypeDef *hdma, uint32_t tim_channel,
uint16_t num_pixels, ARGB_LED_TYPE led_type,
ARGB_DMA_SIZE dma_size, uint8_t use_gamma,
#ifdef ARGB_USE_DYNAMIC_BUFFERS
ARGB_Malloc malloc, ARGB_Free free
#else
uint8_t *rgb_buf, void *pwm_buf
#endif
);
/**
* @brief 反初始化LED灯带
* @param[in] hargb ARGB句柄指针
*/
void ARGB_DeInit(ARGB_HandleTypeDef *hargb);
/**
* @brief 清空所有LED(设置为黑色)
* @param[in] hargb ARGB句柄指针
*/
void ARGB_Clear(ARGB_HandleTypeDef *hargb);
/**
* @brief 设置全局LED亮度
* @param[in] hargb ARGB句柄指针
* @param[in] br 亮度值 [0..255]
*/
void ARGB_SetBrightness(ARGB_HandleTypeDef *hargb, uint8_t br);
/**
* @brief 按索引设置LED的RGB颜色
* @param[in] hargb ARGB句柄指针
* @param[in] i LED位置索引
* @param[in] color RGB颜色结构体
*/
void ARGB_SetRGB(ARGB_HandleTypeDef *hargb, uint16_t i, ARGB_RGB color);
/**
* @brief 按索引设置LED的HSV颜色
* @param[in] hargb ARGB句柄指针
* @param[in] i LED位置索引
* @param[in] hsv HSV颜色结构体
*/
void ARGB_SetHSV(ARGB_HandleTypeDef *hargb, uint16_t i, ARGB_HSV hsv);
/**
* @brief 按索引设置LED的白光分量
* @param[in] hargb ARGB句柄指针
* @param[in] i LED位置索引
* @param[in] w 白光值 [0..255]
* @note 仅SK6812支持白光通道
*/
void ARGB_SetWhite(ARGB_HandleTypeDef *hargb, uint16_t i, uint8_t w);
/**
* @brief 用RGB颜色填充所有LED
* @param[in] hargb ARGB句柄指针
* @param[in] color RGB颜色结构体
*/
void ARGB_FillRGB(ARGB_HandleTypeDef *hargb, ARGB_RGB color);
/**
* @brief 用HSV颜色填充所有LED
* @param[in] hargb ARGB句柄指针
* @param[in] hsv HSV颜色结构体
*/
void ARGB_FillHSV(ARGB_HandleTypeDef *hargb, ARGB_HSV hsv);
/**
* @brief 设置所有LED的白光分量
* @param[in] hargb ARGB句柄指针
* @param[in] w 白光值 [0..255]
* @note 仅SK6812支持白光通道
*/
void ARGB_FillWhite(ARGB_HandleTypeDef *hargb, uint8_t w);
/**
* @brief 获取当前DMA状态
* @param[in] hargb ARGB句柄指针
* @return ARGB_STATE 状态枚举
*/
ARGB_STATE ARGB_Ready(ARGB_HandleTypeDef *hargb);
/**
* @brief 更新灯带显示
* @param[in] hargb ARGB句柄指针
* @return ARGB_STATE 状态枚举
* @note 调用此函数将缓冲区数据通过DMA发送到LED灯带
*/
ARGB_STATE ARGB_Show(ARGB_HandleTypeDef *hargb);
/// @}
#endif /* ARGB_H_ */