1.實驗簡述
使用 PWM+DMA 的方式驅(qū)動 WS2812B,并每隔 800ms 隨機(jī)顯示不同顏色。
2.實驗硬件
兆易創(chuàng)新GD32F310 MCU開發(fā)板套件
16*16 WS2812B
3.開發(fā)環(huán)境
keil 5.24.1
4.WS2812B講解
WS2812B 是 WorldSemi 公司推出的外控集成 RGB LED 光源。
WS2812B 則是將控制 IC 和傳統(tǒng) RGB 結(jié)合到了一起,我們使用一條數(shù)據(jù)線即可驅(qū)動所有 RGB,另外也使得顏色控制的精度更高,同時也支持 RGB 燈組的單個 RGB 顏色控制,因此WS2812B 除了可以用于照明外,還能應(yīng)用到辦公樓外墻來作為屏幕進(jìn)行廣告宣傳,此時每個WS2812B 就對應(yīng)的是一個像素點。
WS2812B 數(shù)據(jù)協(xié)議采用單線歸零碼的通訊方式,像素點在上電復(fù)位以后,DIN 端接受從控制器傳輸過來的數(shù)據(jù),首先送過來的 24bit 數(shù)據(jù)(紅綠藍(lán)各 8 位)被第一個像素點提取后,送到像素點內(nèi)部的數(shù)據(jù)鎖存器,剩余的數(shù)據(jù)經(jīng)過內(nèi)部整形處理電路整形放大后通過 DO端口開始轉(zhuǎn)發(fā)輸出給下一個級聯(lián)的像素點,每經(jīng)過一個像素點的傳輸,信號減少 24bit。
像素點采用自動整形轉(zhuǎn)發(fā)技術(shù),使得該像素點的級聯(lián)個數(shù)不受信號傳送的限制,僅僅受限信號傳輸速度要求。WS2812B 傳輸協(xié)議時序圖如下:
從時序圖可以看到,二進(jìn)制的 0 和 1 用周期相同的不同占空比的方波來表示(1 對應(yīng) 68%占空比,0 對應(yīng) 32%占空比),因此我們可以通過改變 PWM 的占空比來模擬出要傳輸?shù)臄?shù)據(jù)。因為WS2812B 協(xié)議對傳輸速度要求非常高,所以使用了 DMA+PWM 這種方法,在比較事件發(fā)生時,DMA 立即響應(yīng)并將對應(yīng)數(shù)據(jù)傳輸?shù)奖容^寄存器中。
WS2812 的傳輸過程如下圖:
每經(jīng)過一個 WS2812B,數(shù)據(jù)就被截走24bit。
WS2812B 的 24 位數(shù)據(jù)如下:
數(shù)據(jù)按照高位在前的順序分別輸出綠色,紅色和藍(lán)色控制數(shù)據(jù)。在這里我們順便說一下RGB 的取色原理。RGB 由三種基本色構(gòu)成,分別是紅,綠,藍(lán),也叫加法三原色,通過這三種顏色的不同比例可以組合出各種顏色,而不同比例可以通過 PWM 的占空比來實現(xiàn)。如果想要特定顏色,可以使用調(diào)色板取色,如下圖:
5.實驗步驟
1、獲取demo工程,任意選中一個工程用來修改實現(xiàn)PWM+DMA控制WS2812B 功能
2、添加需要的頭文件和宏定義
TIMER0_CH0CC為定時器1的CH0通道比較輸出的地址。
num為要控制ws2812B的數(shù)量,這里我們只控制1個。
3、定義需要的變量和聲明需要的初化函數(shù)
RGB_buffer數(shù)組用來存放占空比數(shù)值。
4、配置PWM輸出引腳
5、配置定時器0通道0輸出PWM
`void timer_config(void)
{
timer_oc_parameter_struct timer_ocintpara; timer_parameter_struct timer_initpara; rcu_periph_clock_enable(RCU_TIMER0); timer_deinit(TIMER0); /* TIMER0 configuration */ timer_initpara.prescaler = 0; timer_initpara.alignedmode = TIMER_COUNTER_EDGE; timer_initpara.counterdirection = TIMER_COUNTER_UP; timer_initpara.period = 89; timer_initpara.clockdivision = TIMER_CKDIV_DIV1; timer_initpara.repetitioncounter = 0; timer_init(TIMER0, &timer_initpara); /* CH0 configuration in PWM0 mode */ timer_ocintpara.outputstate = TIMER_CCX_ENABLE; timer_ocintpara.outputnstate = TIMER_CCXN_ENABLE; timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH; timer_ocintpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH; timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_HIGH; timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; timer_channel_output_config(TIMER0, TIMER_CH_0, &timer_ocintpara); timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_0,0); timer_channel_output_mode_config(TIMER0, TIMER_CH_0, TIMER_OC_MODE_PWM0); timer_channel_output_shadow_config(TIMER0, TIMER_CH_0, TIMER_OC_SHADOW_ENABLE); /* TIMER0 primary output enable */ timer_primary_output_config(TIMER0, ENABLE); /* TIMER0 CH0D DMA request enable */ timer_dma_enable(TIMER0, TIMER_DMA_CH0D); /* auto-reload preload enable */ //timer_auto_reload_shadow_enable(TIMER0); timer_auto_reload_shadow_disable(TIMER0); /* TIMER0 counter enable */ timer_enable(TIMER0);
}`
6、DMA配置
`void dma_config(void)
{
dma_parameter_struct dma_init_struct; /* enable DMA clock */ rcu_periph_clock_enable(RCU_DMA); /* initialize DMA channel1 */ dma_deinit(DMA_CH1); /* DMA channel1 initialize */ dma_deinit(DMA_CH1); dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; dma_init_struct.memory_addr = (uint32_t)RGB_buffer; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT; dma_init_struct.number =sizeof(RGB_buffer); dma_init_struct.periph_addr = (uint32_t)TIMER0_CH0CC; dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT; dma_init_struct.priority = DMA_PRIORITY_HIGH; dma_init(DMA_CH1, &dma_init_struct); /* configure DMA mode */ dma_circulation_disable(DMA_CH1); dma_memory_to_memory_disable(DMA_CH1); /* enable DMA channel1 */ dma_channel_enable(DMA_CH1);
}`
7、通過PWM模擬WS2812B數(shù)據(jù)協(xié)議實現(xiàn)顏色設(shè)置
`void setRGB(uint8_t red,uint8_t green,uint8_t blue)
{
uint8_t i = 0,j =0;
uint32_t rgb_value = green<<16 | red<<8 | blue;
while(dma_flag_get(DMA_CH1, DMA_INTF_FTFIF)==RESET); dma_flag_clear(DMA_CH1,DMA_INTC_FTFIFC); dma_channel_disable(DMA_CH1); dma_transfer_number_config(DMA_CH1,sizeof(RGB_buffer)); for(j=1;j<=num;++j) { for(i=0;i<24;++i) { if((rgb_value<
}`
8、在主函數(shù)實現(xiàn)每隔 800ms 隨機(jī)顯示不同顏色功能。
`int main(void)
{
systick_config(); gpio_config(); dma_config(); timer_config(); usart0_gpio_config(); usart0_config(); /* print out */ printf("Hello world!\n\r"); while(1) { setRGB(rand()%256,rand()%256,rand()%256); delay_1ms(800); };
}`
審核編輯:劉清
-
PWM
+關(guān)注
關(guān)注
114文章
5201瀏覽量
214959 -
MCU芯片
+關(guān)注
關(guān)注
3文章
254瀏覽量
11651 -
WS2812B
+關(guān)注
關(guān)注
2文章
38瀏覽量
2309
發(fā)布評論請先 登錄
相關(guān)推薦
什么是WS2812B?WS2812B燈帶是怎么連接的呢?
![什么是<b class='flag-5'>WS2812B</b>?<b class='flag-5'>WS2812B</b>燈帶是怎么連接的呢?](https://file1.elecfans.com/web2/M00/8C/48/wKgZomSpB9SANNq4AAB5cHm0z7c704.jpg)
STM32F030 MDA+PWM驅(qū)動ws2812b,起始的50US的低電平是怎么產(chǎn)生?
WS2812B RGB全彩LED燈珠
使用DMA+PWM方式驅(qū)動ws2812
怎樣使用硬件定時器PWM+DMA方式實現(xiàn)WS2812的驅(qū)動呢
怎樣給WS2812B發(fā)送數(shù)據(jù)呢
怎樣使用PWM+DMA的方式去驅(qū)動WS2812B呢
可以用SPI DMA去驅(qū)動WS2812b嗎?
CH563驅(qū)動ws2812B使用SPI+DMA呢還是用PWM+DMA呢?
STM32使用LL庫PWM的DMA模式驅(qū)動ws2812
![STM32使用LL庫<b class='flag-5'>PWM</b>的<b class='flag-5'>DMA</b>模式<b class='flag-5'>驅(qū)動</b><b class='flag-5'>ws2812</b>](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
STM32F1 DMA+PWM 控制WS2812B LED燈
![STM32F1 <b class='flag-5'>DMA+PWM</b> 控制<b class='flag-5'>WS2812B</b> LED燈](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
PWM+DMA 驅(qū)動 WS2812
![<b class='flag-5'>PWM+DMA</b> <b class='flag-5'>驅(qū)動</b> <b class='flag-5'>WS2812</b>](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
WS2812B遠(yuǎn)程區(qū)域面板控制器
![<b class='flag-5'>WS2812B</b>遠(yuǎn)程區(qū)域面板控制器](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
ESP32 WS2812b分線板開源分享
![ESP32 <b class='flag-5'>WS2812b</b>分線板開源分享](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
WS2812B遙控?zé)艨刂破?/a>
![<b class='flag-5'>WS2812B</b>遙控?zé)艨刂破? /> </a>
</div> </div> </div><!-- .main-wrap -->
</article>
<aside class=](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
評論