WS2811的時序波形如下圖:
注意:這里是低速模式(400KHz)的時間要求,我們用的是800KHz,需要把時間除以2.
我們的RGB方案是將RGB數據通過DMA發送到timer的CCR寄存器,動態改變timer輸出的PWM占空比,來驅動RGB。這里DMA發送給timer的數據,是我們經過轉換的RGB所需的時序數據。
這個方案的重點是理解怎么轉化這個RGB需要的時序數據!
【在設定好自動重裝載寄存器ARR = 35后,動態改變比較寄存器TIMx_CCRx的值,來達到改變輸出的占空比的目的】
先把相關關鍵代碼貼出來!
1.定時器配置,重點是 【計數器自動重載寄存器 (TIMERx_CAR)】=34+1
1 timer_initpara.prescaler = 2; //時鍾預分頻數 84M/(34+1)/(2+1) = 0.8mHz = 800KHz 2 timer_initpara.alignedmode = TIMER_COUNTER_EDGE; //向上&向下都是邊沿對齊 3 timer_initpara.counterdirection = TIMER_COUNTER_UP; 4 timer_initpara.period = 34; /* 自動重裝載寄存器周期的值(計數值) */ 5 timer_initpara.clockdivision = TIMER_CKDIV_DIV1; 6 timer_initpara.repetitioncounter = 0; 7 timer_init(TIMER3, &timer_initpara);
2.RGB的邏輯數據
1 // BLUE data 2 for ( j = 0; j < 8; j++ ) 3 { 4 if ( ( color[ led ][ 2 ] << j ) & 0x80 ) // data sent MSB first, j = 0 is MSB j = 7 is LSB 5 { 6 if(memaddr<500) 7 { 8 LED_BYTE_Buffer[ memaddr ] = 17; // compare value for logical 1 9 } 10 } 11 else 12 { 13 if(memaddr<500) 14 { 15 LED_BYTE_Buffer[ memaddr ] = 9; // compare value for logical 0 16 } 17 } 18 memaddr++; 19 }
好了,現在可以進行解析這段美妙的代碼邏輯了。
我們知道WS2811是有自己的1 code & 0 code的時序要求的,就拿0 code來分析。
我們想要發給WS2811一個0,就需要發一個占空比如下的波形:
WS2811所需的時鍾周期是1/800KHz = 1.25us
T0H = 0.5us/2 ± 0.15us = 0.25 ± 0.15us
帶入數據計算:
(35-27)/35 * 1.25 us = 0.32 us;滿足T0H的時間要求。
同理 T0L = 2.0us/2 ± 0.15us = (35-9)/35*1.25us = 0.93 us;滿足T0L的要求
當讀懂這段代碼時真的是豁然開朗並驚為天人,這種應用真是太帥了!