打印
[N32G43x]

【N32G435x】用PWM+DMA驱动WS281X RGB彩灯的产品级源码分享

[复制链接]
6599|73
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 6552918 于 2022-3-4 22:43 编辑

#申请原创#  

@21小跑堂

这次的N32优质帖征集活动不错,可以更好的体验国民技术的通用MCU的特点,能够让大家更深入的体验国民的通用MCU,也能让大家看到更多的干货,在此我来抛个砖!!!
这次分享的是使用PWM+DMA驱动WS2812B(兼容WS2811)的方式和源码,源码内支持查询驱动方式和中断驱动方式,是一款可以产品级应用的方式,在此源码基础上可以根据自己的需求修改即可。
下面我们先看看RGB彩灯WS2812B和WS2811的简单介绍
WS2812B和WS2811在供电;驱动数量;24bit数据结构和0 1码高低电平定义上有差别,但大致是兼容的,在代码里我通过宏定义进行了兼容。
接下来我介绍一下具体源码
源码由5个文件组成
delay.c               ->  官方BSP内的延时函数  支持微妙 毫秒延时
delay.h              ->  官方BSP内的延时函数头文件
n32g43x_it.c          ->  中断函数文件
WS281X.c              ->  WS2812B和WS2811的驱动文件
WS281X.h             ->  WS2812B和WS2811的驱动文件头文件
delay.c和delay.h是国民官方BSP内的延时函数文件,文件内实现的us和ms延时函数,可以方便的使用,在使用相关延时函数前需要调用void delay_init(void)对系统时钟进行初始化。
我重点介绍一下n32g43x_it.c ;WS281X.c ;WS281X.h这3个文件

WS281X.h内定义了和灯珠驱动的相关宏定义
//#define WS2811                      ->   芯片为WS2811开启此宏    两宏互斥
#define WS2812B                       ->   芯片为WS2812B开启此宏  两宏互斥
#define PWM_DMA_IRQ            ->   使用PWM DMA中断开启此宏

#define   PIXEL_NUM1  4      //灯带1灯数(组数)
#define   PIXEL_NUM2  3      //灯带2灯数(组数)
#define   PIXEL_NUM3  2      //灯带3灯数(组数)
#define   PIXEL_NUM4  1      //灯带4灯数(组数)
#define   PIXEL_NUM5  1         //灯带5灯数(组数)
#define   PIXEL_NUM    (PIXEL_NUM1+PIXEL_NUM2+PIXEL_NUM3+PIXEL_NUM4+PIXEL_NUM5)   定义了驱动的灯数(组数);

定义了WS2811和WS2812B的0 1码PWM占空比定义,这里WS_HIGH和WS_LOW的值会再后面初始化函数时介绍。

接下来我来介绍一下WS281X.c这个文件
函数void WS281x_Init(void) 对PWM输出用到的GPIO进行了初始化;对PWM输出相关的定时器进行了初始化,对PWM输出相关的DMA进行了初始化; 对PWM输出相关的中断进行了初始化;在相关外设初始化前要打开相关外设的时钟。
PWM输出使用GPIOA的6脚(TIM3的通道1),开启复用模式

这里DMA使用的是通道2,在开启DMA模式时通过宏定义PWM_DMA_IRQ开启了DMA的NVIC相关操作。
这里重点介绍一下N32G435的DMA,尽管通道不多,但真的十分灵活,所有请求都可以映射到任意8个通道上,这让使用变得非常自由。DMA_RequestRemap(DMA_REMAP_TIM3_UP, DMA, DMA_CH2, ENABLE);这个函数实现了请求与通道的映射。

DMA_InitStructure.BufSize        = 0;    //传输次数-》为0不发送
当DMA传输次数为0时,即使有相关请求也不会进行传输操作!!!
在这里使用更新事件触发DMA请求。
在定时器相关初始化过程中,涉及到PWM的周期和占空比问题,在用户手册中相关描述如下:
在函数中相关参数为
TIM_TimeBaseInitStruct.Period= 68 - 1;  /* 54M / 68 = 794.12K (小于800K) */
(TIM3的时钟总线最大频率为54M,而WS2812B的数据发送速度最大为800K,所以将TIM3_AR寄存器值设定为68(794.12K约等于1.26us),以便将输出频率控制在最接近800K的速率以内。)
TIM_OCInitStruct.Pulse= 0;  (对应的寄存器为TIM3_CDDATx的值,此值由DMA进行传输赋值,以便控制占空比。)
在开启DMA模式时通过宏定义PWM_DMA_IRQ开启了TIM3的NVIC相关操作。

外设初始化完成后,还要对灯珠进行初始化,就行将所要控制的灯珠,都设置为熄灭状态。
void WS281x_CloseAll(void) 函数将显示buffer全部填充为“0”(0码对应的占空比数值),再通过WS281x_Show();控制PWM输出开始。

WS281x_Show()内,先检查DMA传输次数是否为0,不为0说明传输未完成,需要等待完成,再将TIM3_CDDATx的值清0,然后在关闭DMA通道情况下对传输次数赋值,然后开启通道,最后使能TIM3就开始PWM的输出了。在使用查询方式输出情况下,使用PWM_DMA_IRQ宏控制的部分是查询传输是否完成的相关操作。这部分涉及到2块内容,一块是DMA传输是否完成,领一部分是PWM输出是否完成,因为DMA传输完成是先于PWM输出完成的,为保证WS2812B的控制信号准确,要在PWM传输完成后马上关闭PWM输出才行。
本文件的其他函数是和显示效果相关的,可以根据自己的需求选择,再此就不详细介绍了。

当使用PWM+DMA中断传输方式,就涉及到n32g43x_it.c文件的内容。
由于开启PWM+DMA中断方式后,DMA传输完中断先产生,会先进void DMA_Channel2_IRQHandler(void)函数,在函数内确认是传输完中断后进入相关操作,先清除传输完成标志,关闭通道,然后再开启TIM的更新中断,在PWM完成最后一个周期的输出后进入TIM3的更新中断,再更新中断内要先清除TIM3_CDDAT1为0(以便保证输出为低电平,在下图中显示,如果TIM3_CDDAT1不为0,有可能会使输出为高电平,这样是不满足WS2812B的时序要求的),然后清除更新中断标志,关闭TIM3,禁用TIM3的更新中断。
至此,在使用PWM+DMA驱动WS2812B(兼容WS2811)的整个过程就介绍完成,相关源码一并提供,希望对有需求的朋友有所帮助。
源码在附件中,欢迎大家下载。


PWM DMA.zip

7.95 KB

使用特权

评论回复
沙发
yljon| | 2022-1-24 10:36 | 只看该作者
不错啊

使用特权

评论回复
板凳
两只袜子| | 2022-1-24 11:29 | 只看该作者
有源码的东西真的是好东西

使用特权

评论回复
评论
6552918 2022-1-24 13:11 回复TA
有板子可以试试 
地板
kyzhd| | 2022-1-26 09:09 | 只看该作者
楼主的灯条好好看哟,学习了,感谢楼主。

使用特权

评论回复
5
duo点| | 2022-2-13 10:35 | 只看该作者
感谢楼主分享

使用特权

评论回复
6
chenjun89| | 2022-2-14 18:35 | 只看该作者
不错,感谢分享。

使用特权

评论回复
7
alvpeg| | 2022-3-3 22:09 | 只看该作者
WS281X 使用定时器可以吗

使用特权

评论回复
8
i1mcu| | 2022-3-3 22:26 | 只看该作者
N32G435 用的pwm可行?

使用特权

评论回复
9
6552918|  楼主 | 2022-3-3 22:35 | 只看该作者
alvpeg 发表于 2022-3-3 22:09
WS281X 使用定时器可以吗

定时器不就是用PWM吗?

使用特权

评论回复
10
6552918|  楼主 | 2022-3-3 22:35 | 只看该作者
i1mcu 发表于 2022-3-3 22:26
N32G435 用的pwm可行?

必须可以,我就是用435调试的

使用特权

评论回复
11
nomomy| | 2022-3-3 22:42 | 只看该作者
如何用dma修改pwm呢

使用特权

评论回复
12
vivilyly| | 2022-3-3 23:04 | 只看该作者
以前用过延时操作。  

使用特权

评论回复
13
earlmax| | 2022-3-3 23:31 | 只看该作者
最多支持多少个WS281X RGB彩灯

使用特权

评论回复
评论
6552918 2022-3-4 08:51 回复TA
这要看你串还是并,和内存是否够用 
14
robincotton| | 2022-3-4 20:00 | 只看该作者
不是可以spi+dma吗

使用特权

评论回复
评论
6552918 2022-3-4 22:15 回复TA
可以,但有时想调到合适的0码和1码有点困难,我用过SPI方式,某些频率会有问题 
15
单片小菜| | 2022-3-7 10:37 | 只看该作者
感谢楼主的分享,不错的一个案例哦。

使用特权

评论回复
16
七毛钱| | 2022-3-11 10:05 | 只看该作者
这个值得学习的案例

使用特权

评论回复
17
起点116| | 2022-3-11 22:09 | 只看该作者
感谢分享

使用特权

评论回复
18
primojones| | 2022-3-16 20:47 | 只看该作者
最大支持多少的控制  

使用特权

评论回复
19
htmlme| | 2022-3-16 21:15 | 只看该作者
WS281X RGB彩灯效果怎么样

使用特权

评论回复
20
showgu| | 2022-3-16 21:40 | 只看该作者
我倾向于用SPI 引脚方式。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:北京汇冠触摸技术有限公司/电子工程师
简介:电子工程师,嵌入式应用爱好者。

102

主题

1249

帖子

9

粉丝