基于 STM32CubeMX + PWM + DMA驱动SW2812b全彩RGB灯
STM32CubeMX配置:
- 勾选烧录脚
- 配置高速外部时钟
- 选择PWM通道和引脚
- 配置DMA:
- 定时器周期配置:
- 时钟树配置(最好是配置单片机最大时钟):
- 添加工程文件以及名字生成cubeMX工程。
工程源码:
rgb.c文件
#include "rgb.h"
#include "main.h"
#include "tim.h"
#define ONE_PULSE (40) //1 码
#define ZERO_PULSE (20) //0 码
#define RESET_PULSE (60) //80 ,复位信号
#define LED_NUMS (10) //led 数量
#define LED_DATA_LEN (24) //led 长度,单个需要24bits
#define WS2812_DATA_LEN (LED_NUMS*LED_DATA_LEN) //ws2812灯条需要的数组长度
//uint16_t static RGB_buffur[RESET_PULSE + WS2812_DATA_LEN] = { 0 };
uint16_t RGB_buffur[RESET_PULSE + WS2812_DATA_LEN] = { 0 };
void ws2812_set_RGB(uint8_t R, uint8_t G, uint8_t B, uint16_t num)
{
//
uint16_t* p = (RGB_buffur + RESET_PULSE) + (num * LED_DATA_LEN);
for (uint16_t i = 0;i < 8;i++)
{
//
p[i] = (G << i) & (0x80)?ONE_PULSE:ZERO_PULSE;
p[i + 8] = (R << i) & (0x80)?ONE_PULSE:ZERO_PULSE;
p[i + 16] = (B << i) & (0x80)?ONE_PULSE:ZERO_PULSE;
}
}
/*ws2812 初始化*/
void ws2812_init(uint8_t led_nums)
{
uint16_t num_data;
num_data = 60 + led_nums * 24;
for(uint8_t i = 0; i < led_nums; i++)
{
ws2812_set_RGB(0x00, 0x00, 0x00, i);
}
HAL_TIM_PWM_Start_DMA(&htim3,TIM_CHANNEL_3,(uint32_t *)RGB_buffur,(num_data));
}
/*全亮蓝灯*/
void ws2812_blue(uint8_t led_nums)
{
uint16_t num_data;
num_data = 60 + led_nums * 24;
for(uint8_t i = 0; i < led_nums; i++)
{
ws2812_set_RGB(0x00, 0x00, 0x22, i);
}
HAL_TIM_PWM_Start_DMA(&htim3,TIM_CHANNEL_3,(uint32_t *)RGB_buffur,(num_data));
}
/*全亮红灯*/
void ws2812_red(uint8_t led_nums)
{
uint16_t num_data;
num_data = 60 + led_nums * 24;
for(uint8_t i = 0; i < led_nums; i++)
{
ws2812_set_RGB(0x22, 0x00, 0x00, i);
}
HAL_TIM_PWM_Start_DMA(&htim3,TIM_CHANNEL_3,(uint32_t *)RGB_buffur,(num_data));
}
/*全亮绿灯*/
void ws2812_green(uint8_t led_nums)
{
uint16_t num_data;
num_data = 60 + led_nums * 24;
for(uint8_t i = 0; i < led_nums; i++)
{
ws2812_set_RGB(0x00, 0x22, 0x00, i);
}
HAL_TIM_PWM_Start_DMA(&htim3,TIM_CHANNEL_3,(uint32_t *)RGB_buffur,(num_data));
}
void ws2812_example(void)
{
ws2812_set_RGB(0x00, 0x00, 0x22, 0);
ws2812_set_RGB(0x00, 0x00, 0x22, 1);
ws2812_set_RGB(0x00, 0x00, 0x22, 2);
ws2812_set_RGB(0x00, 0x00, 0x22, 3);
ws2812_set_RGB(0x00, 0x00, 0x22, 6);
ws2812_set_RGB(0x00, 0x00, 0x22, 7);
// ws2812_set_RGB(0x00, 0x00, 0x22, 8);
// ws2812_set_RGB(0x00, 0x00, 0x22, 10);
HAL_TIM_PWM_Start_DMA(&htim3,TIM_CHANNEL_3,(uint32_t *)RGB_buffur,(60 + 10 * 24)); //344 = 80 + 24 * LED_NUMS(11)
HAL_Delay(500);
}
rgb.h文件
#ifndef _RGB_H_
#define _RGB_H_
#include "main.h"
#include "stdint.h"
#include "type.h"
void ws2812_set_RGB(uint8_t R, uint8_t G, uint8_t B, uint16_t num);
void ws2812_example(void);
extern void ws2812_blue(uint8_t led_nums);
extern void ws2812_red(uint8_t led_nums);
extern void ws2812_green(uint8_t led_nums);
void ws2812_init(uint8_t led_nums);
#endif
time.c 文件中存放DMA数据传送完成回调函数:
/* USER CODE BEGIN 1 */
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
HAL_TIM_PWM_Stop_DMA(&htim3,TIM_CHANNEL_3);
}
/* USER CODE END 1 */
type.h 类型名的重命名文件
#ifndef _TYPE_H_
#define _TYPE_H_
#include "main.h"
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <stdbool.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
typedef volatile uint8_t vu8;
typedef volatile uint16_t vu16;
typedef volatile uint32_t vu32;
typedef volatile int8_t vs8;
typedef volatile int16_t vs16;
typedef volatile int32_t vs32;
typedef union{
s8 s8_fmt[8]; //for angle and omega
u8 u8_fmt[8]; //for angle and omega
char ch_fmt[8]; //
s16 s16_fmt[4];
u16 u16_fmt[4];
s32 s32_fmt[2];
u32 u32_fmt[2];
float f32_fmt[2];
double d64_fmt;
}data_convert_ut; //for diaobi gyro
#endif
main.c 文件的编写:
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
MX_TIM3_Init();
/* USER CODE BEGIN 2 */
//HAL_TIM_PWM_Start_DMA(&htim3,TIM_CHANNEL_3,(uint32_t *)RGB_buffur,(num_data));
设置默认的å 空比å€?
//__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_3,40);
// WS2812_Display_2( 22 , 0 , 0, 0);
// WS2812_Display_2( 0 , 22, 0, 1);
// WS2812_Display_2( 0 , 0, 22, 2);
// WS2812_Display_2( 255, 0 , 255, 3);
// HAL_TIM_PWM_Start_DMA(&htim3,TIM_CHANNEL_3,(uint32_t *)RGB_buffur,(176));//å¯åŠ¨DMAä¼ è¾“
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
ws2812_init(10);// 所有RGB小灯的初始化 --- 10个
uint16_t num_data;
num_data = 60 + 10 * 24;
for(uint8_t i = 0; i < 10; i++)
{
ws2812_set_RGB(0x50, 0x50, 0x50, i);//0x50 小灯最亮
}
HAL_TIM_PWM_Start_DMA(&htim3,TIM_CHANNEL_3,(uint32_t *)RGB_buffur,(num_data));
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}