STM32F103C8T6点亮WS2812灯,软件:STM32CubeIDE
/ 纯白色点击查看更多颜色代码。
·
所需材料
-
开发板:STM32F103C8T6,我用的是B站博主keysking
-
材料:WS2812灯带,杜邦线
-
相关配置:GPIO,DMA,TIM
-
软件:STM32CubeIDE
步骤
-
打开软件,新建工程
-
设置 RCC 和 SYS


-
设置TIM2
-
Clock Source 选择 Internal Clock,开启 TIM3 的内部时钟源,引脚使用 PA15,Prescaler 配置为 0,Counter Period配置为90-1。

设置DMA
点击DMA Setting,添加DMA通道

设置GPIO

-
时钟树将HCLK频率配置为 72 MHz

-
单独生成.c / .h 文件

-
按下Ctrl + S 生成工程
-
添加WS2812.c 和 WS2812.h 文件
注意在 void ws2812_update(void)函数中的HAL_TIM_PWM_Start_DMA(&htim2, TIM_CHANNEL_1, ,如果你不是TIM2,channel 1,在这里修改
#include "ws2812.h"
#include <math.h>
#include <stdlib.h>
#include <string.h>
// LED颜色
uint32_t ws2812_color[WS2812_NUM] = {0};
// 当前LED颜色
static uint32_t _ws2812_color_current[WS2812_NUM];
/**
* @brief 直接更新LED颜色
*/
void ws2812_update(void)
{
// 数据缓冲,每个LED占用24个字节,共10个LED,前100个字节用于复位信号
static uint16_t ws2812_data[RST_PERIOD_NUM + WS2812_NUM * 24];
for (uint8_t led_id = 0; led_id < WS2812_NUM; led_id++)
{
_ws2812_color_current[led_id] = ws2812_color[led_id];
static uint8_t r, g, b;
color_to_rgb(_ws2812_color_current[led_id], &r, &g, &b);
uint16_t *p = ws2812_data + RST_PERIOD_NUM + led_id * 24;
for (uint8_t i = 0; i < 8; i++)
{
p[i] = (r << i) & (0x80) ? CODE_ONE_DUTY : CODE_ZERO_DUTY;
p[i + 8] = (g << i) & (0x80) ? CODE_ONE_DUTY : CODE_ZERO_DUTY;
p[i + 16] = (b << i) & (0x80) ? CODE_ONE_DUTY : CODE_ZERO_DUTY;
}
}
HAL_TIM_PWM_Start_DMA(&htim2, TIM_CHANNEL_1, (uint32_t *)ws2812_data,
RST_PERIOD_NUM + WS2812_NUM * 24);
}
/**
* @brief 通过渐变方式更新LED颜色(线性插值)
* @param steps: 渐变步数
* @param delay_ms: 每步之间的延迟时间(毫秒)
*/
void ws2812_gradient(uint8_t steps, uint16_t delay_ms)
{
static uint8_t start_r[WS2812_NUM], start_g[WS2812_NUM], start_b[WS2812_NUM];
static float r_step[WS2812_NUM], g_step[WS2812_NUM], b_step[WS2812_NUM];
// 提取初始颜色,并计算每步的渐变步长
for (uint8_t i = 0; i < WS2812_NUM; i++)
{
color_to_rgb(_ws2812_color_current[i], &start_r[i], &start_g[i], &start_b[i]);
uint8_t target_r, target_g, target_b;
color_to_rgb(ws2812_color[i], &target_r, &target_g, &target_b);
r_step[i] = (float)(target_r - start_r[i]) / steps;
g_step[i] = (float)(target_g - start_g[i]) / steps;
b_step[i] = (float)(target_b - start_b[i]) / steps;
}
// 逐步渐变
for (uint8_t step = 1; step <= steps; step++)
{
for (uint8_t led_id = 0; led_id < WS2812_NUM; led_id++)
{
// 计算当前步的颜色
uint8_t r = (uint8_t)(start_r[led_id] + r_step[led_id] * step);
uint8_t g = (uint8_t)(start_g[led_id] + g_step[led_id] * step);
uint8_t b = (uint8_t)(start_b[led_id] + b_step[led_id] * step);
ws2812_set_rgb(led_id, r, g, b);
}
ws2812_update();
HAL_Delay(delay_ms);
}
}
/**
* @brief 设置LED颜色(RGB格式)
* @param led_id: LED编号(学习板一共有10个LED,编号范围0-9)
* @param r: 红色亮度(0-255)
* @param g: 绿色亮度(0-255)
* @param b: 蓝色亮度(0-255)
*/
void ws2812_set_rgb(uint8_t led_id, uint8_t r, uint8_t g, uint8_t b)
{
ws2812_color[led_id] = rgb_to_color(r, g, b);
}
/**
* @brief 设置LED颜色(24bit颜色格式)
* @param led_id: LED编号(学习板一共有10个LED,编号范围0-9)
* @param color: 24bit颜色
*/
void ws2812_set(uint8_t led_id, uint32_t color)
{
ws2812_color[led_id] = color;
}
/**
* @brief 设置所有LED颜色(24bit颜色格式)
* @param color: 24bit颜色
*/
void ws2812_set_all(uint32_t color)
{
for (uint8_t led_id = 0; led_id < WS2812_NUM; led_id++)
{
ws2812_color[led_id] = color;
}
}
/**
* @brief RGB转换为24bit颜色
* @param r: 红色亮度(0-255)
* @param g: 绿色亮度(0-255)
* @param b: 蓝色亮度(0-255)
* @retval 24bit颜色
*/
uint32_t rgb_to_color(uint8_t r, uint8_t g, uint8_t b)
{
return (r << 16) | (g << 8) | b;
}
/**
* @brief 24bit颜色转换为RGB
* @param color: 24bit颜色
* @param r: 红色亮度(0-255)
* @param g: 绿色亮度(0-255)
* @param b: 蓝色亮度(0-255)
*/
void color_to_rgb(uint32_t color, uint8_t *r, uint8_t *g, uint8_t *b)
{
*r = (color >> 16) & 0xFF;
*g = (color >> 8) & 0xFF;
*b = color & 0xFF;
}
注意 #define WS2812_NUM ,这是灯带LED的数量
#ifndef __WS2812_H__
#define __WS2812_H__
#include "main.h"
#include "gpio.h"
#include "tim.h"
#include "stdio.h"
#include "string.h"
#define CODE_ONE_DUTY 66
#define CODE_ZERO_DUTY 21
// #define CODE_ONE_DUTY 90
// #define CODE_ZERO_DUTY 32
#define RST_PERIOD_NUM 100
#define WS2812_NUM 60 //灯带LED灯数量
extern uint32_t ws2812_color[WS2812_NUM];
// 将颜色数组直接更新到 LED,不使用渐变过渡
void ws2812_update(void);
// 渐变的更新LED颜色
void ws2812_gradient(uint8_t steps, uint16_t delay_ms);
// 设置LED颜色(24bit颜色)
void ws2812_set(uint8_t led_id, uint32_t color);
// 设置LED颜色(RGB)
void ws2812_set_rgb(uint8_t led_id, uint8_t r, uint8_t g, uint8_t b);
// 设置所有LED颜色
void ws2812_set_all(uint32_t color);
// RGB转换为24bit颜色
uint32_t rgb_to_color(uint8_t r, uint8_t g, uint8_t b);
// 24bit颜色转换为RGB
void color_to_rgb(uint32_t color, uint8_t *r, uint8_t *g, uint8_t *b);
#endif
-
最后在主函数 while (1) 循环添加代码
ws2812_set_all(0xFFFFFF); // 纯白色
ws2812_gradient(200, 3);
ws2812_update();
更多推荐



所有评论(0)