一、模塊介紹
WS2812B是一種流行的可編程LED模塊,通常被稱為“NeoPixel”。它是一種智能LED燈模塊,具有以下主要特點(diǎn)和功能:
1. 集成性:WS2812B模塊集成了一個(gè)RGB LED和一個(gè)控制芯片,這意味著每個(gè)模塊都包含了完整的LED驅(qū)動(dòng)電路,而不需要外部元件。
2. 可編程:每個(gè)WS2812B模塊都可以通過單個(gè)數(shù)據(jù)線進(jìn)行編程和控制。通過發(fā)送適當(dāng)?shù)臄?shù)據(jù)信號(hào),您可以精確地控制LED的顏色和亮度。
3. 鏈接性:多個(gè)WS2812B模塊可以鏈接在一起,形成一個(gè)LED燈帶、LED矩陣或其他形狀,以創(chuàng)建更大的光效。
4. 低電壓工作:WS2812B模塊通常在5V電源下工作,但也有3.3V版本。這使得它們適用于各種不同的電子項(xiàng)目。
5. 簡化控制:WS2812B模塊的控制相對(duì)簡單,因?yàn)樗鼈冎恍枰粋€(gè)數(shù)據(jù)信號(hào)線來控制。這使得它們易于與微控制器(如Arduino)或單片機(jī)等嵌入式系統(tǒng)集成。
6. RGB控制:每個(gè)WS2812B模塊都包含一個(gè)紅色(R)、綠色(G)和藍(lán)色(B)LED,允許您混合這些顏色來創(chuàng)建各種顏色效果。
7. 亮度控制:您可以通過調(diào)整數(shù)據(jù)信號(hào)中的亮度值來控制LED的亮度級(jí)別,從而創(chuàng)建不同的光效。
WS2812B模塊廣泛用于各種應(yīng)用,如彩色LED照明、LED藝術(shù)裝置、LED顯示屏和互動(dòng)裝置。它們的靈活性和易于控制使它們成為電子愛好者和制造商的熱門選擇,用于創(chuàng)建令人驚嘆的LED項(xiàng)目。要使用WS2812B模塊,您通常需要了解如何編程控制它們,以及如何提供適當(dāng)?shù)碾娫春瓦B接。
二、資料獲取
關(guān)注微信公眾號(hào)--星之援工作室 發(fā)送關(guān)鍵字(WS2812B)
????
三、 實(shí)驗(yàn)器材
1.單片機(jī):STM32F103C8T6
2.元器件:8燈珠的WS2812B
3.端口占用:WS2812B -- PA2
四、實(shí)現(xiàn)效果
跑馬燈效果,漸變色
五、主要代碼
WS2812B.c
#include "WS2812B.h"
uint16_t LED_BYTE_Buffer[24]; //發(fā)送數(shù)組緩存
uint32_t LED_WORD_Buffer[8];
void WS2812B_TIM_init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* GPIOA Configuration: TIM2 Channel 1 as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
/* Compute the prescaler value */
//PrescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1;
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 89; // 800kHz
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
/* PWM1 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_OC3Init(TIM2, &TIM_OCInitStructure);
/* configure DMA */
/* DMA clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* DMA1 Channel6 Config */
DMA_DeInit(DMA1_Channel2);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&TIM2->CCR3; // 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 = 24;
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_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel2, &DMA_InitStructure);
/* TIM3 CC1 DMA Request enable */
/* 只能使用通道1 TIMx_UP */
TIM_DMACmd(TIM2, TIM_DMA_Update, ENABLE);
}
void send_Data(uint32_t rgb)
{
uint8_t r = (rgb&0xff0000)>>16;
uint8_t g = (rgb&0x00ff00)>>8;
uint8_t b = (rgb&0xff);
for(uint16_t i=0;i<8;i++){
LED_BYTE_Buffer[i] = (0x80&g)>0?TIMING_ONE:TIMING_ZERO;g <<= 1;
}
for(uint16_t i=0;i<8;i++){
LED_BYTE_Buffer[8 + i] = (0x80&r)>0?TIMING_ONE:TIMING_ZERO;r <<= 1;
}
for(uint16_t i=0;i<8;i++){
LED_BYTE_Buffer[16 + i] = (0x80&b)>0?TIMING_ONE:TIMING_ZERO;b <<= 1;
}
DMA_SetCurrDataCounter(DMA1_Channel2, 24); // load number of bytes to be transferred
DMA_Cmd(DMA1_Channel2, ENABLE); // enable DMA channel 6
TIM_Cmd(TIM2, ENABLE); // enable Timer 3
while(!DMA_GetFlagStatus(DMA1_FLAG_TC2)) ; // wait until transfer complete
TIM_Cmd(TIM2, DISABLE); // disable Timer 3
DMA_Cmd(DMA1_Channel2, DISABLE); // disable DMA channel 6
DMA_ClearFlag(DMA1_FLAG_TC2); // clear DMA1 Channel 6 transfer complete flag
}
WS2812B.h
#ifndef __WS2812B_H
#define __WS2812B_H
#include "stm32f10x.h"
#define TIMING_ONE 50 //T1H 1碼
#define TIMING_ZERO 25 //T0L 0碼
void WS2812B_TIM_init(void);
void send_Data(uint32_t rgb);
#endif //__WS2812B_H
main.c
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "WS2812B.h"
#include <stdlib.h>
uint32_t *RGB;//顏色列表數(shù)組
void LED_Init(void);
void PWM_Init(void);
uint32_t set_Color_Loop(uint8_t color_length);
void out_RGB(uint16_t data_Max_Length,uint16_t colorwidth);
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
uart_init(115200);
delay_init();
LED_Init();
WS2812B_TIM_init();
uint32_t len = set_Color_Loop(32);//每兩種顏色之間的位數(shù)
while(1)
{
out_RGB(len,8);//8個(gè)燈,每次輸出8個(gè)數(shù)據(jù)
delay_ms(80);
}
}
/**
* colorwidth 每次獲取多少位
*/
void out_RGB(uint16_t data_Max_Length,uint16_t colorwidth)
{
static uint32_t rgb_position = 0;
for(uint32_t i = 0;i < colorwidth; i++){
uint16_t c = (rgb_position + i) % data_Max_Length;//末尾顏色數(shù)據(jù)結(jié)束時(shí)將首位的收據(jù)填充到數(shù)組
send_Data(RGB[c]);
}
rgb_position ++;
rgb_position %= data_Max_Length;
}
/**
* color_length 每種顏色漸變最大長度,總顏色長度:color_length * 3
* return 顏色數(shù)據(jù)總長度
*/
uint32_t set_Color_Loop(uint8_t color_length)
{
RGB = (uint32_t*)malloc(color_length*3*sizeof(uint32_t));//分配數(shù)組大小,(所有漸變色顏色長度)
color_length -= 1;
for(uint8_t i=0;i<=color_length;i++)
{
RGB[i] = (((0xff/color_length)*i)<<8)|((0xff/color_length)*(color_length-i)); //藍(lán)到綠
RGB[color_length + 1 +i] = (((0xff/color_length)*i)<<16)|((0xff/color_length)*(color_length-i))<<8; //綠到紅
RGB[((color_length+1)*2) +i] = ((0xff/color_length)*i)|((0xff/color_length)*(color_length-i))<<16; //紅到藍(lán)
}
return color_length*3;
}
void LED_Init()
{
GPIO_InitTypeDef GPIO_InitTypeStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitTypeStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitTypeStruct.GPIO_Pin = GPIO_Pin_5;
GPIO_InitTypeStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE,&GPIO_InitTypeStruct);
GPIO_InitTypeStruct.GPIO_Pin = GPIO_Pin_5;
GPIO_Init(GPIOB,&GPIO_InitTypeStruct);
GPIOB->ODR ^= GPIO_Pin_5;
GPIOE->ODR ^= GPIO_Pin_5;
}
六、參考
【STM32】WS2812B燈珠的PWM+DMA控制(庫函數(shù))https://blog.csdn.net/ii1i2huo/article/details/122619197?ops_request_misc=&request_id=&biz_id=102&utm_term=ws2812b%E6%B5%81%E6%B0%B4%E7%81%AFstm32%E5%90%AF%E5%8A%A8&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-2-122619197.142^v96^pc_search_result_base7&spm=1018.2226.3001.4187
完整代碼請關(guān)注衛(wèi)星公眾號(hào)進(jìn)行獲取和咨詢
聯(lián)系方式 微信號(hào):13648103287