項目中需要對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();