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();

     

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM