一、WS2812介紹
WS2812是一種廣泛使用的地址可控制的RGB LED模塊,其內置驅動電路和控制芯片,允許用戶通過單線信號控制多個LED的顏色和亮度。以下是WS2812模塊的一些主要特點和應用:
主要特點
單線控制: WS2812模塊通過單一數據線進行控制,簡化了連接線的復雜度。
地址可控: 每個WS2812 LED都有獨立的地址,這意味著你可以分別控制每個LED的顏色和亮度,適合制作動態效果。
多彩顯示: 支持全彩顯示,通常可以混合紅色、綠色和藍色三基色,產生多種顏色。
鏈式連接: 支持多顆WS2812 LED串聯,可以方便地擴展LED的數量,只需將下一顆LED的數據線連接到前一顆LED上。
高亮度和高密度: WS2812 LED具有較高的亮度,可以在較大面積上提供均勻的光效,適合室內外裝飾和顯示。
控制精度: 通常提供256級亮度(8位)和1670萬種顏色選擇,確保豐富的視覺效果。
主控制板上的WS2812部分如下圖:

原理圖
主控制板上WS2812模塊的接線圖如下:

可以看到一共有八個模塊級聯在一起,并且由PA12控制。
通信原理
WS2812的數據協議采用單線歸零碼的通訊方式,支持串行級聯接口,能通過一根信號線完成數據的接收與解碼。每個燈就是一個像素點,每個像素點的三基色顏色可實現256級亮度顯示,完成16777216種顏色的全真色彩顯示。
像素點在上電復位以后,DIN端接受從控制器傳輸過來的數據,首先送過來的24bit數據被第一個像素點提取后,送到像素點內部的數據鎖存器,剩余的數據經過內部整形處理電路整 形放大后通過DO端口開始轉發輸出給下一個級聯的像素點,每經過一個像素點的傳輸,信號減少24bit。像素點采用自動整形轉發技術,使得該像素點的級聯個數不受信號傳送的限制,僅受限信號傳輸速度要求。
控制方式
因為使用的是單總線,一根線完成一個燈要顯示的24位顏色數據,是通過高低電平的時間長度來確定發送的是什么數據。24位的數據結構見下圖。

其中G代表三色中的綠色,R代表三色中的紅色,B表示三色中的藍色。例如想要只顯示紅色則發送 0X00FF00即可。
控制時序
發送24位顏色數據,是通過高低電平的時間長度來確定發送的是0還是1。

發送一位數據0,需要總線拉高T0H的時間再拉低T0L的時間,WS2812才會自動識別該數據是0。
發送一位數據1,需要總線拉高T1H的時間再拉低T1L的時間,WS2812才會自動識別該數據是1。
二、驅動代碼編寫
WS2812的驅動方法有很多種,定時器+DMA,SPI+DMA,軟件模擬等,我們這里選擇軟件模擬時序的方式來驅動。
首先初始化GPIO口,將PA12口配置為推挽輸出。注意CW32F030和CW32L012的時鐘配置區別。
void WS2812_Init(void)
{
__RCC_GPIOA_CLK_ENABLE();//開啟時鐘
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.IT=GPIO_IT_NONE;
GPIO_InitStruct.Mode=GPIO_MODE_OUTPUT_PP;//推挽輸出
GPIO_InitStruct.Pins=GPIO_PIN_12;
GPIO_InitStruct.Speed=GPIO_SPEED_HIGH;
GPIO_Init(CW_GPIOA, &GPIO_InitStruct);
RGB_Color_Init();//初始化所有燈
}
隨后根據時序的高低電平要求,先編寫一個ns延時,由于當前使用主頻為64mhz,可以算出一個機器指令所需時間大概為1/64=15ns,然后加上GPIO電平翻轉時間即可。
/**************************
400ns延時
**************************/
void delay_400ns(void)//409
{
__nop();__nop();__nop();__nop();__nop();//__nop();__nop();
}
/**************************
800ns延時
**************************/
void delay_800ns(void)//800
{
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
// __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
// __nop();__nop();
}
然后根據時序所需的高低電平時間編寫0,1指令
/**************************
發送1
**************************/
void RGB_Send1(void)
{
RGB_H;
delay_800ns();
RGB_L;
delay_400ns();
}
/**************************
發送0
**************************/
void RGB_Send0(void)
{
RGB_H;
delay_400ns();
RGB_L;
delay_800ns();
}
然后就可以向芯片發送指令了,一個顏色分為RGB三個色域,一個色域為8位,所以我們需要八位數據一起發送,編寫如下代碼:
/**************************
發送顏色數據,高位先行
**************************/
void RGB_send_Data(uint8_t Data)
{
uint8_t i;
for(i=0;i8;i++)
{
if(Data & 0x80)
{
RGB_Send1();
}
else
{
RGB_Send0();
}
Data<=1;
}
}
這樣就可以向芯片發送指定的顏色數據啦,最后在封裝一下,我們想要的要求是指定某個燈亮某種顏色,或者指定某個燈熄滅,不能影響到其他燈,所以我們定義一個數組來裝下所有燈的顏色數據,到時候只需要改變數組中固定位置的值就可以直接改變顏色了,代碼如下:
/**************************
顯示顏色
n:第幾個燈
R:紅色
G:綠色
B:藍色
**************************/
void Send_RGB(uint8_t n,uint8_t R,uint8_t G,uint8_t B)
{
uint8_t i;
RGB_Data[3*n-3]=G;
RGB_Data[3*n-2]=R;
RGB_Data[3*n-1]=B;
for(i=0;i24;i++)
{
RGB_send_Data(RGB_Data[i]);
}
RGB_Reset();
}
最后在main函數編寫如下代碼(OLED顯示代碼不在此處列出)
int main(void)
{
OLED_Init();//初始化
OLED_ShowString(1,1,"Hello");//OLED顯示字符串
WS2812_Init();
while(1)
{
Send_RGB(1,255,0,0);//255,0,0對應紅色
Delay_ms(500);
Send_RGB(1,0,255,0);//255,0,0對應綠色
Delay_ms(500);
Send_RGB(1,0,0,255);//255,0,0對應藍色
Delay_ms(500);
}
}
三、工作現象
在燒寫代碼之后,我們可以觀察到以下現象,OLED第一行第一列顯示HELLO,第一個RGB燈每隔500ms轉換一次顏色,在紅綠藍三色之間反復切換。

-
led
+關注
關注
243文章
24594瀏覽量
690821 -
RGB
+關注
關注
4文章
831瀏覽量
61939 -
驅動電路
+關注
關注
158文章
1622瀏覽量
111630 -
智能小車
+關注
關注
87文章
560瀏覽量
83430
發布評論請先 登錄
CW32L012/F030靈眸X1智能小車——超聲波模塊配置
STM32F030 MDA+PWM驅動ws2812b,起始的50US的低電平是怎么產生?
【RA4L1-SENSOR】點亮 WS2812 全彩點陣屏
**CW32L012****開發評估板的第一個程序**
CW32L012小型機器人控制評估板活動 四足機器人+智能小車 開箱評測
使用DMA+PWM方式驅動ws2812
Arduino控制WS2812燈帶的方法
STM32F103C8T6+PWM+DMA驅動WS2812燈帶的方法
WS2812驅動的總結和時序的詳細資料分析
STM32使用LL庫PWM的DMA模式驅動ws2812
STM32F103C8T6+PWM+DMA驅動 WS2812燈帶
PWM+DMA 驅動 WS2812
如何使用智能手機控制16x16 WS2812 Led矩陣
CW32L012與STM32F103的三角運算性能對比
CW32L012/F030靈眸X1智能小車——板載WS2812驅動示例
評論