STM32 G431RB 中实现对WS2812灯带的控制(PWM + DMA)
项目中需要对WS2812灯带进行控制,项目中的灯带是21颗等,需求要求对所有的LED等设置颜色的时候是统一的颜色,
如果需要设置不同的颜色,也可以参考代码进行修改。
实现方式是 PWM + DMA的方式,一次将21颗灯的颜色值都设定好。
参考的是这篇英文文章来实现的。 Interface WS2812 with STM32(https://controllerstech.com/interface-ws2812-with-stm32/)
我的代码实放在Github上了。 https://github.com/magicduan/demo_pwm_dma
我的板子是G431RB,处理上稍微有些不同,详细的原理等就不在这里说明了,这里整理一下按照这个参考例子开发出的问题。
- Direction需要设置为 "Memory To Peripheral",也就是将Memory的内容搬运到PWM寄存器中。开始设置的时候没有注意,时间浪费了。
- Mode 设置为"Normal", 有的例子文章说要设置为"Circular". "Normal"与"Circular"的区别是,"Normal" Mode下DMA搬运完数据后就不再自动继续搬了,“Circular” Mode会自动的循环搬运数据
- 英文文章中Data Width 是Peripheral :Half Word, Memory:Half Word. 选Half Word的原因是PWM的Counter Period是16 bit的。我之前是参考英文文章做的,这样处理没有什么问题,就是PWM 的Buffer的需要用uint16_t保存Duty Value。而我的Counter Period是(75-1),也就是最大值是75,使用uint8_t就可以,这样能节省一半的内存。 由于其他代码的需要我这边的代码的实际处理是 Presaler = 15-1, Counter Period = 5-1.
- 由于我Memory的Data Width是Byte,这里就碰见了字节对齐问题
- Buffer声明的时候需要边界对齐
-
#define DMA_TYPE uint8_t __attribute__((aligned(4))) volatile DMA_TYPE pwm_buffer[BUFFER_LEN];
- 今天碰见一个巨大的坑,STM32 CubeIDE生成代码的时候有Bug,在main函数中DMA初始化顺序与TIM的初始化顺序的问题,STM32 CubeIDE有时候生成的是反的,反了DMA执行就会被卡在,执行不成功。花了很长时间比较代码才找出来。具体的原因参考这篇CSD的文章(STM32 DMA传输的Bug)
- 正常顺序:
-
MX_DMA_Init(); MX_TIM1_Init();
错误顺序:
-
MX_TIM1_Init(); MX_DMA_Init();
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)