当前位置:   article > 正文

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

stm32驱动ws2812

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

WS2812模块介绍

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

经典电路

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

实物展示

在这里插入图片描述

点亮灯光

// An highlighted block
void controlMultipleLEDs() {
    // 控制LED 0
    colors[0][0] = 255; // 设置为红色
    colors[0][1] = 0;
    colors[0][2] = 0;

    // 控制LED 1
    colors[1][0] = 0;   // 设置为绿色
    colors[1][1] = 255;
    colors[1][2] = 0;
	    // 控制LED 2
    colors[2][0] = 0;   // 设置为蓝色
    colors[2][1] = 255;
    colors[2][2] = 0;
		    // 控制LED 3
    colors[3][0] = 100;   
    colors[3][1] = 200;
    colors[3][2] = 155;
		    // 控制LED 4
    colors[4][0] = 55;   
    colors[4][1] = 0;
    colors[4][2] = 0;


    // 调用WS2812_Send函数发送颜色数据
    WS2812_Send(colors, NUM_LEDS);
}


  • 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

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 bytes
	memaddr = 0;				// reset buffer memory index

	
	if(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 transferred
		DMA_Cmd(DMA1_Channel7, ENABLE); 			// enable DMA channel 7
		TIM_Cmd(TIM2, ENABLE); 						// enable Timer 2
		while(!DMA_GetFlagStatus(DMA1_FLAG_TC7)) ; 	// wait until transfer complete
		DMA_Cmd(DMA1_Channel7, DISABLE); 			// disable DMA channel 7
		DMA_ClearFlag(DMA1_FLAG_TC7); 				// clear DMA1 Channel 7 transfer complete flag
		TIM_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 0
    colors[0][0] = 255; // 设置为红色
    colors[0][1] = 0;
    colors[0][2] = 0;

    // 控制LED 1
    colors[1][0] = 0;   // 设置为绿色
    colors[1][1] = 255;
    colors[1][2] = 0;
	    // 控制LED 2
    colors[2][0] = 0;   // 设置为蓝色
    colors[2][1] = 255;
    colors[2][2] = 0;
		    // 控制LED 3
    colors[3][0] = 100;   // 设置为蓝色
    colors[3][1] = 200;
    colors[3][2] = 155;
		    // 控制LED 4
    colors[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 0
	for(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);
	}
}
			}
		}

    
}


  • 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

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
	
}

  • 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

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 CCR1
	DMA_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 peripheral
	DMA_InitStructure.DMA_BufferSize = 300;
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;					// automatically increase buffer index
	DMA_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 reached
	DMA_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 CCR1
	DMA_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 peripheral
	DMA_InitStructure.DMA_BufferSize = 300;
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;					// automatically increase buffer index
	DMA_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 reached
	DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
	
	DMA_Init(DMA1_Channel5, &DMA_InitStructure);

	
	
}

  • 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

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.h

int main (void){
	RCC_Configuration();//系统时钟初始化
	TIM2_PWM_Init(77,0);	//初始化PWM
	TIM2_DMA_Init();		//初始化DMA
	InitLED();

	while(1){ 
		
			//WS2812_Red_BLN();				//红色呼吸灯
		//	WS2812_Green_BLN();			//绿色呼吸灯
		//	WS2812_Blue_BLN();			//蓝色呼吸灯
		//	WS2812_Random();			//随机闪灯
		//controlMultipleLEDs();
		controlDiffentLEDs();
			
	}

}





  • 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

需要源码可评论留言。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/71113?site
推荐阅读
相关标签
  

闽ICP备14008679号