返回列表 发新帖我要提问本帖赏金: 20.00元(功能说明)

[活动专区] 【AT-START-M412测评】TIM+DMA方式驱动WS2812色环

[复制链接]
 楼主| 阿源玩电子 发表于 2025-6-22 18:38 | 显示全部楼层 |阅读模式
本帖最后由 阿源玩电子 于 2025-6-22 18:40 编辑

#申请原创#
TIM3+DMA方式驱动WS2812色环



WS2812介绍
WS2812智能LED通过单线NRZ(Non-Return-to-Zero)通信协议传输数据,每个LED需要接收24位(3字节)数据,分别对应G(绿色)、R(红色)、B(蓝色)三种颜色的亮度值(每种颜色8位)



2.WS2812通信时序详解

bb89e316b87c62194fd3951fa181b78c.png

典型时序参数:
  • 逻辑"1": 高电平约800ns,低电平约450ns
  • 逻辑"0": 高电平约400ns,低电平约850ns
  • 每个bit周期固定为1.25μs (±150n)
3.通信思路

定时器+PWM实现

  • 使用PWM占空比区分逻辑1和逻辑0
  • 设置PWM周期为1.25μs
  • 逻辑1:占空比64%(800ns高电平)
  • 逻辑0:占空比32%(400ns高电平)
ecc056ca70e82e35d70b5af4c3ce8d18.png

4.AT32_Work_Bench工程配置

  • 配置TIM3通道一,设置定时器周期

5ec6af1d6a24ba0a6133434e5357ba7a.png

  • DMA设置

1b36c291e2a4a4982df58f8c5a20d61f.png

  • 开启DMA传输中断

89accb77ef8ecfb12867889aba0e56bc.png

5.生成工程

定义WS2812.h文件

  1. #ifndef __WS2812_H
  2. #define __WS2812_H

  3. #include "at32m412_416.h"   // 使用AT32 MCU的硬件驱动头文件

  4. // ====================
  5. // 硬件相关配置定义
  6. // ====================

  7. /* WS2812数据位时序定义 */
  8. #define RGB_led_bit_1       121  // 逻辑"1"的PWM比较值
  9. #define RGB_led_bit_0       61   // 逻辑"0"的PWM比较值

  10. /* LED灯带配置 */
  11. #define led_data_length     24   // 每个LED需要24位数据(GRB各8位)
  12. #define RGB_PIXEL_NUM       24   // 最大支持LED数量

  13. // ====================
  14. // 数据结构定义
  15. // ====================

  16. /**
  17. * [url=home.php?mod=space&uid=247401]@brief[/url] WS2812数据缓冲区的联合体定义
  18. *
  19. * 使用二维数组存储所有LED的24位数据:
  20. * - 第一维: LED索引(0~RGB_PIXEL_NUM-1)
  21. * - 第二维: 24位数据(8位G + 8位R + 8位B)
  22. */
  23. typedef union _rgbPixelBuffer {
  24.     uint16_t All_Buffer[RGB_PIXEL_NUM][led_data_length];
  25. } RGB_PixelBuffer, *PRGB_PixelBuffer;

  26. // ====================
  27. // 全局变量声明
  28. // ====================

  29. extern RGB_PixelBuffer RGB_Buffer;  // 全局数据缓冲区

  30. // ====================
  31. // 函数声明
  32. // ====================

  33. void WS2812_Update(void);
  34. void RGB_Write_Led_Bit(uint32_t RGB, uint16_t Index);
  35. void RGB_Write_Led_Bit_AllLedSame(uint32_t RGB, uint16_t numLeds);

  36. #endif /* __WS2812_H */
定义WS2812.c文件

  1. #include "ws2812.h"

  2. RGB_PixelBuffer RGB_Buffer={0};

  3. /**
  4.   * [url=home.php?mod=space&uid=247401]@brief[/url]  设置特定LED的RGB颜色。
  5.   * @param  RGB: 组合后的RGB颜色值,格式为0x00RRGGBB。
  6.   * @param  Index: 要写入的LED索引。
  7.   * @retval None.
  8.   */
  9. void RGB_Write_Led_Bit(uint32_t RGB, uint16_t Index) {
  10.     uint16_t led_index = Index;
  11.     uint8_t  green= (RGB >> 16);  
  12.     uint8_t  red= (RGB >> 8);  
  13.     uint8_t blue = RGB;        
  14.     for (uint8_t n = 0; n < 8; n++) {
  15.         RGB_Buffer.All_Buffer[led_index][0 * 8 + n] = (red & (0x80 >> n)) ? RGB_led_bit_1 : RGB_led_bit_0;
  16.         RGB_Buffer.All_Buffer[led_index][1 * 8 + n] = (green & (0x80 >> n)) ? RGB_led_bit_1 : RGB_led_bit_0;
  17.         RGB_Buffer.All_Buffer[led_index][2 * 8 + n] = (blue & (0x80 >> n)) ? RGB_led_bit_1 : RGB_led_bit_0;
  18.     }
  19. }


  20. /**
  21.   * @brief  同时点亮所有LED为相同的RGB颜色。
  22.   * @param  RGB: 组合后的RGB颜色值,格式为0x00RRGGBB。
  23.   * @param  numLeds: LED的数量。
  24.   * @retval None.
  25.   */
  26. void RGB_Write_Led_Bit_AllLedSame(uint32_t RGB, uint16_t numLeds) {
  27.     for (uint16_t i = 0; i < numLeds; i++) {
  28.         RGB_Write_Led_Bit(RGB, i);
  29.     }
  30. }

  31. // 启动DMA传输
  32. void WS2812_Update(void) {
  33.             if((dma_data_number_get(DMA1_CHANNEL1) != 0))
  34.                 {
  35.                         return;
  36.                 }else
  37.                 {
  38.                          tmr_channel_value_set(TMR3, TMR_SELECT_CHANNEL_1, 0);               
  39.              tmr_counter_enable(TMR3, FALSE);
  40.              dma_channel_enable(DMA1_CHANNEL1, FALSE);
  41.              dma_data_number_set(DMA1_CHANNEL1, (RGB_PIXEL_NUM * 24));
  42.                          dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE);                        
  43.                          tmr_dma_request_enable(TMR3, TMR_C1_DMA_REQUEST, TRUE);        
  44.              dma_channel_enable(DMA1_CHANNEL1, TRUE);
  45.        tmr_counter_enable(TMR3, TRUE);
  46.                 }                        
  47. }
DMA中断处理

  1. void DMA1_Channel1_IRQHandler(void)
  2. {
  3.   /* add user code begin DMA1_Channel1_IRQ 0 */
  4.     if (dma_flag_get(DMA1_FDT1_FLAG) != RESET)
  5.     {
  6.                           tmr_dma_request_enable(TMR3, TMR_C1_DMA_REQUEST, FALSE);
  7.                                 tmr_channel_value_set(TMR3, TMR_SELECT_CHANNEL_1, 0);
  8.         dma_channel_enable(DMA1_CHANNEL1, FALSE);
  9.                           dma_flag_clear(DMA1_FDT1_FLAG);
  10.     }  
  11.   /* add user code end DMA1_Channel1_IRQ 0 */
  12.   /* add user code begin DMA1_Channel1_IRQ 1 */

  13.   /* add user code end DMA1_Channel1_IRQ 1 */
  14. }
6.波形检查(符合时序要求)

43bb95e2412e421cb00dc142cd3920f7.jpg

7.点亮效果

732b4358b2bbe3094c021f1eb70f0875.jpg 7969b93e8d96830c73b492c8d28a395f.jpg e0a8cbe5c5cce6bb36420fd69920fa83.jpg





AT32M412CBT7_WS2812.zip

3.09 MB, 下载次数: 6

驱动工程文件

打赏榜单

ArteryMCU 打赏了 20.00 元 2025-07-04
理由:[M412开发板评测活动]内容优质

您需要登录后才可以回帖 登录 | 注册

本版积分规则

12

主题

33

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部