WS2812模塊介紹
WS2812是一顆數(shù)字LED燈珠,采用單總線通訊,每顆燈珠支持24bit的顏色控制,也即RGB888,信號(hào)線通過DIN輸入,經(jīng)過一顆燈珠之后,信號(hào)線上前24bit數(shù)據(jù)會(huì)被該燈珠鎖存,之后將剩下的數(shù)據(jù)信號(hào)整形之后通過DOUT輸出
經(jīng)典電路
C1為VDD的濾波電容,一般大小為100NF。
實(shí)物展示
點(diǎn)亮燈光
// An highlighted block
void controlMultipleLEDs() {
// 控制LED 0
colors[0][0] = 255; // 設(shè)置為紅色
colors[0][1] = 0;
colors[0][2] = 0;
// 控制LED 1
colors[1][0] = 0; // 設(shè)置為綠色
colors[1][1] = 255;
colors[1][2] = 0;
// 控制LED 2
colors[2][0] = 0; // 設(shè)置為藍(lán)色
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;
// 調(diào)用WS2812_Send函數(shù)發(fā)送顏色數(shù)據(jù)
WS2812_Send(colors, NUM_LEDS);
}
WS2812.c
// An highlighted block
#include "ws2812b.h"
#include "stdlib.h"
#include "delay.h"
#define NUM_LEDS 10 // 假設(shè)有5個(gè)LED
uint8_t colors[NUM_LEDS][3]; // 每個(gè)LED有3個(gè)顏色通道(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; //控制燈光的數(shù)量
} //
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:最后一個(gè)周期波形是高電平,故增加一個(gè)低電平的波形
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() //隨機(jī)閃燈
{
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() //藍(lán)色呼吸燈
{
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; // 藍(lán)色通道
// 調(diào)用WS2812_Send函數(shù)發(fā)送顏色數(shù)據(jù)
WS2812_Send(colors, NUM_LEDS);
}
delay_ms(1000);
}
void controlMultipleLEDs() {
// 控制LED 0
colors[0][0] = 255; // 設(shè)置為紅色
colors[0][1] = 0;
colors[0][2] = 0;
// 控制LED 1
colors[1][0] = 0; // 設(shè)置為綠色
colors[1][1] = 255;
colors[1][2] = 0;
// 控制LED 2
colors[2][0] = 0; // 設(shè)置為藍(lán)色
colors[2][1] = 255;
colors[2][2] = 0;
// 控制LED 3
colors[3][0] = 100; // 設(shè)置為藍(lán)色
colors[3][1] = 200;
colors[3][2] = 155;
// 控制LED 4
colors[4][0] = 55; // 設(shè)置為藍(lán)色
colors[4][1] = 0;
colors[4][2] = 0;
// 調(diào)用WS2812_Send函數(shù)發(fā)送顏色數(shù)據(jù)
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; // 設(shè)置為紅色
colors[j][1] = a;
colors[j][2] = b;
// 調(diào)用WS2812_Send函數(shù)發(fā)送顏色數(shù)據(jù)
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選擇全復(fù)用功能使能
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);//修復(fù)DMA數(shù)據(jù)丟失
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初始化設(shè)置
/* configure DMA */
DMA_InitTypeDef DMA_InitStructure;//定義DMA初始化結(jié)構(gòu)體
/* DMA clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE); //使能DMA時(shí)鐘(用于SPI的數(shù)據(jù)傳輸)
/* 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初始化設(shè)置
/* configure DMA */
DMA_InitTypeDef DMA_InitStructure;//定義DMA初始化結(jié)構(gòu)體
/* DMA clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE); //使能DMA時(shí)鐘(用于SPI的數(shù)據(jù)傳輸)
/* 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);
}
main.c文章來源:http://www.zghlxwxcb.cn/news/detail-855857.html
// An highlighted block
#include "dma.h"
#include "pwm.h"
#include "delay.h"
#include "ws2812b.h"
#include "stm32f10x.h"
#include "sys.h"
//需要更改標(biāo)準(zhǔn)庫中的sys.h和delay.h
int main (void){
RCC_Configuration();//系統(tǒng)時(shí)鐘初始化
TIM2_PWM_Init(77,0); //初始化PWM
TIM2_DMA_Init(); //初始化DMA
InitLED();
while(1){
//WS2812_Red_BLN(); //紅色呼吸燈
// WS2812_Green_BLN(); //綠色呼吸燈
// WS2812_Blue_BLN(); //藍(lán)色呼吸燈
// WS2812_Random(); //隨機(jī)閃燈
//controlMultipleLEDs();
controlDiffentLEDs();
}
}
需要源碼可評(píng)論留言。文章來源地址http://www.zghlxwxcb.cn/news/detail-855857.html
到了這里,關(guān)于STM32+PWM+DMA驅(qū)動(dòng)WS2812彩燈模塊(評(píng)論點(diǎn)贊給源代碼)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!