STM32用PWM +DMA驱动 WS2811原理解析

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的要求

 

 

 当读懂这段代码时真的是豁然开朗并惊为天人,这种应用真是太帅了!

 

posted @ 2021-12-03 14:32  xjxcxjx  阅读(4784)  评论(0编辑  收藏  举报