STM32+PWM+DMA驱动WS2812彩灯模块(附源码)

STM32+PWM+DMA驱动WS2812彩灯模块

  • WS2812模块介绍
    • 经典电路
    • 实物展示
  • 点亮灯光

WS2812模块介绍

WS2812是一颗数字LED灯珠,采用单总线通讯,每颗灯珠支持24bit的颜色控制,也即RGB888,信号线通过DIN输入,经过一颗灯珠之后,信号线上前24bit数据会被该灯珠锁存,之后将剩下的数据信号整形之后通过DOUT输出
引脚功能图

经典电路

电路图
C1为VDD的滤波电容,一般大小为100NF。

实物展示

在这里插入图片描述

点亮灯光

// An highlighted block
void controlMultipleLEDs() {// 控制LED 0colors[0][0] = 255; // 设置为红色colors[0][1] = 0;colors[0][2] = 0;// 控制LED 1colors[1][0] = 0;   // 设置为绿色colors[1][1] = 255;colors[1][2] = 0;// 控制LED 2colors[2][0] = 0;   // 设置为蓝色colors[2][1] = 255;colors[2][2] = 0;// 控制LED 3colors[3][0] = 100;   colors[3][1] = 200;colors[3][2] = 155;// 控制LED 4colors[4][0] = 55;   colors[4][1] = 0;colors[4][2] = 0;// 调用WS2812_Send函数发送颜色数据WS2812_Send(colors, NUM_LEDS);
}

WS2812.c

// An highlighted block
#include "ws2812b.h"
#include "stdlib.h"
#include "delay.h"#define NUM_LEDS 10 // 假设有5个LED
uint8_t colors[NUM_LEDS][3]; // 每个LED有3个颜色通道(RGB)void WS2812_Send(uint8_t (*color)[3], uint16_t len)
{uint8_t i;uint16_t memaddr;uint16_t buffersize;buffersize = (len*24)+43;	// number of bytes needed is #LEDs * 24 bytes + 42 trailing bytesmemaddr = 0;				// reset buffer memory indexif(len>NUM_LEDS){//len=NUM_LEDS;    //控制灯光的数量}                //while (len){	for(i=0; i<8; i++) // RED{LED_BYTE_Buffer[memaddr] = ((color[len-1][1]<<i) & 0x0080) ? TIMING_ONE:TIMING_ZERO;memaddr++;}for(i=0; i<8; i++) // GREEN data{LED_BYTE_Buffer[memaddr] = ((color[len-1][0]<<i) & 0x0080) ? TIMING_ONE:TIMING_ZERO;memaddr++;}for(i=0; i<8; i++) // BLUE{LED_BYTE_Buffer[memaddr] = ((color[len-1][2]<<i) & 0x0080) ? TIMING_ONE:TIMING_ZERO;memaddr++;}len--;}
//===================================================================//	
//bug:最后一个周期波形是高电平,故增加一个低电平的波形LED_BYTE_Buffer[memaddr] = 0;
//===================================================================//	memaddr++;	while(memaddr < buffersize){LED_BYTE_Buffer[memaddr] = 0;memaddr++;}DMA_SetCurrDataCounter(DMA1_Channel7, buffersize); 	// load number of bytes to be transferredDMA_Cmd(DMA1_Channel7, ENABLE); 			// enable DMA channel 7TIM_Cmd(TIM2, ENABLE); 						// enable Timer 2while(!DMA_GetFlagStatus(DMA1_FLAG_TC7)) ; 	// wait until transfer completeDMA_Cmd(DMA1_Channel7, DISABLE); 			// disable DMA channel 7DMA_ClearFlag(DMA1_FLAG_TC7); 				// clear DMA1 Channel 7 transfer complete flagTIM_Cmd(TIM2, DISABLE); 	// disable Timer 2
}//呼吸灯代码//
void WS2812_Random()	//随机闪灯
{uint8_t rgb0[1][3];rgb0[0][0] = rand()%256;rgb0[0][1] = rand()%256;rgb0[0][2] = rand()%256;WS2812_Send(&rgb0[0],1);delay_ms(1);
}void WS2812_Red_BLN()	//红色呼吸灯
{u16 i;uint8_t rgb0[256][3] ={0,0,0};for(i=0;i<=255;i++){rgb0[i][0] = i;}for(i=0;i<=255;i++){WS2812_Send(&rgb0[i],1);delay_ms(5);}for(i=0;i<=255;i++){rgb0[i][0] = (255 - i);}for(i=0;i<=255;i++){WS2812_Send(&rgb0[i],1);delay_ms(5);}delay_ms(500);}void WS2812_Green_BLN()	//绿色呼吸灯
{u16 i;uint8_t rgb0[256][3] ={0,0,0};for(i=0;i<=255;i++){rgb0[i][1] = i;}for(i=0;i<=255;i++){WS2812_Send(&rgb0[i],1);delay_ms(5);}for(i=0;i<=255;i++){rgb0[i][1] = (255 - i);}for(i=0;i<=255;i++){WS2812_Send(&rgb0[i],1);delay_ms(5);}delay_ms(500);
}
void WS2812_Blue_BLN()	//蓝色呼吸灯
{u16 i;uint8_t rgb0[256][3] ={0,0,0};for(i=0;i<=255;i++){rgb0[i][2] = i;}for(i=0;i<=255;i++){WS2812_Send(&rgb0[i],1);delay_ms(5);}for(i=0;i<=255;i++){rgb0[i][2] = (255 - i);}for(i=0;i<=255;i++){WS2812_Send(&rgb0[i],1);delay_ms(5);}delay_ms(500);
}	//单色灯代码////初始化灯光
void InitLED()
{u16 i = 0;for (i = 0; i < NUM_LEDS; i++) {colors[i][0] = 255; // 红色通道colors[i][1] = 0;   // 绿色通道colors[i][2] = 0;   // 蓝色通道// 调用WS2812_Send函数发送颜色数据WS2812_Send(colors, NUM_LEDS);}delay_ms(1000);}void controlMultipleLEDs() {// 控制LED 0colors[0][0] = 255; // 设置为红色colors[0][1] = 0;colors[0][2] = 0;// 控制LED 1colors[1][0] = 0;   // 设置为绿色colors[1][1] = 255;colors[1][2] = 0;// 控制LED 2colors[2][0] = 0;   // 设置为蓝色colors[2][1] = 255;colors[2][2] = 0;// 控制LED 3colors[3][0] = 100;   // 设置为蓝色colors[3][1] = 200;colors[3][2] = 155;// 控制LED 4colors[4][0] = 55;   // 设置为蓝色colors[4][1] = 0;colors[4][2] = 0;// 调用WS2812_Send函数发送颜色数据WS2812_Send(colors, NUM_LEDS);
}void controlDiffentLEDs() {u16 i;u16 j;u16 a;u16 b;// 控制LED 0for(i=0;i<255;i++){for(a=100;a<255;a++){for(b=255;b>0;b--){for(j=0;j<NUM_LEDS;j++){colors[j][0] = i; // 设置为红色colors[j][1] = a;colors[j][2] = b;// 调用WS2812_Send函数发送颜色数据WS2812_Send(colors, NUM_LEDS);delay_ms(1);}
}}}}

pwm.c

// An highlighted block
#include "pwm.h"void TIM2_PWM_Init(u16 arr,u16 psc)
{ TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;TIM_OCInitTypeDef  TIM_OCInitStructure;GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);/* GPIOA Configuration: TIM2 Channel 1 as alternate function push-pull */GPIO_PinRemapConfig(GPIO_FullRemap_TIM2, ENABLE); //TIM2选择全复用功能使能 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;				//GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);/* Time base configuration */TIM_TimeBaseStructure.TIM_Period = arr; // 800kHz TIM_TimeBaseStructure.TIM_Prescaler = psc;TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);/* PWM4 Mode configuration: Channel1 */TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;TIM_OCInitStructure.TIM_Pulse = 0;//初始化占空比TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;TIM_OC4Init(TIM2, &TIM_OCInitStructure);TIM_OC4PreloadConfig(TIM2,TIM_OCPreload_Enable);//修复DMA数据丢失TIM_ARRPreloadConfig(TIM2,ENABLE);//ARPE使能 TIM_Cmd(TIM2, ENABLE);  //使能TIM9}

DMA.c

// An highlighted block
#include "dma.h"
uint16_t LED_BYTE_Buffer[300];void TIM2_DMA_Init(void){ //DMA初始化设置/* configure DMA */DMA_InitTypeDef DMA_InitStructure;//定义DMA初始化结构体/* DMA clock enable */RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);	//使能DMA时钟(用于SPI的数据传输)/* DMA1 Channel7 Config for PWM4 by TIM2_CH4*/DMA_DeInit(DMA1_Channel7);DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)TIM2_CCR4_Address;	// physical address of Timer 3 CCR1DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)LED_BYTE_Buffer;		// this is the buffer memory DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;						// data shifted from memory to peripheralDMA_InitStructure.DMA_BufferSize = 300;DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;					// automatically increase buffer indexDMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;							// stop DMA feed after buffer size is reachedDMA_InitStructure.DMA_Priority = DMA_Priority_Medium;DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;DMA_Init(DMA1_Channel7, &DMA_InitStructure);/* TIM2 DMA Request enable */TIM_DMACmd(TIM2, TIM_DMA_CC4, ENABLE);TIM_DMACmd(TIM2, TIM_DMA_Update, ENABLE);}void SPI2_DMA_Init(void){ //DMA初始化设置/* configure DMA */DMA_InitTypeDef DMA_InitStructure;//定义DMA初始化结构体/* DMA clock enable */RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);	//使能DMA时钟(用于SPI的数据传输)/* DMA1 Channel7 Config for PWM4 by TIM2_CH4*/DMA_DeInit(DMA1_Channel5);DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->DR);	// physical address of Timer 3 CCR1DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)LED_BYTE_Buffer;		// this is the buffer memory DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;						// data shifted from memory to peripheralDMA_InitStructure.DMA_BufferSize = 300;DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;					// automatically increase buffer indexDMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;							// stop DMA feed after buffer size is reachedDMA_InitStructure.DMA_Priority = DMA_Priority_Medium;DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;DMA_Init(DMA1_Channel5, &DMA_InitStructure);}

main.c

// An highlighted block
#include "dma.h"
#include "pwm.h"
#include "delay.h"
#include "ws2812b.h"
#include "stm32f10x.h"
#include "sys.h"
//需要更改标准库中的sys.h和delay.hint main (void){RCC_Configuration();//系统时钟初始化TIM2_PWM_Init(77,0);	//初始化PWMTIM2_DMA_Init();		//初始化DMAInitLED();while(1){ //WS2812_Red_BLN();				//红色呼吸灯//	WS2812_Green_BLN();			//绿色呼吸灯//	WS2812_Blue_BLN();			//蓝色呼吸灯//	WS2812_Random();			//随机闪灯//controlMultipleLEDs();controlDiffentLEDs();}}

需要源码可评论留言。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部