硬汉嵌入式论坛

 找回密码
 立即注册
查看: 235|回复: 1
收起左侧

[技术讨论] GD32F470ZG为什么我的PWM DMA无效果 有大佬知道为什么吗

[复制链接]

4

主题

5

回帖

17

积分

新手上路

积分
17
发表于 2025-12-11 10:12:09 | 显示全部楼层 |阅读模式
//PA2-TIMER4-CH2  DMA0 -CH0


#include "bsp_pwm.h"

//#include "ws2812.h"
#include "gd32f4xx.h"


//// 定义RGB_LOGICAL值(根据实际PWM周期计算)
#define RGB_LOGICAL_H 96  // 0.8μs (对应逻辑1)
#define RGB_LOGICAL_L 48   // 0.4μs (对应逻辑0)

// 全局缓冲区(最大支持 个灯珠)
#define MAX_LED_COUNT 4
#define RGB_LEN (MAX_LED_COUNT * 24 + 42)

uint16_t LED_Buff[RGB_LEN];

void Tim4CH2_init_DMA(uint32_t number);

  #define TIMER4_CH2CV  (TIMER4+0x3C)                    /* 通道2 */

void Timer4_init(void)
  {
      rcu_periph_clock_enable(RCU_TIMER4);
      rcu_periph_clock_enable(RCU_GPIOA);
      rcu_periph_clock_enable(RCU_DMA0);

     dma_single_data_parameter_struct dma_data_parameter;
     timer_oc_parameter_struct timer_ocintpara;
     timer_parameter_struct timer_initpara;

     gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_2);
     gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
     gpio_af_set(GPIOA, GPIO_AF_2, GPIO_PIN_2);

     /* TIMER4 configuration */
     timer_initpara.prescaler         = 0;            //时钟预分频数 (200)M/10/25 = 0.8mHz = 800KHz
     timer_initpara.alignedmode         = TIMER_COUNTER_EDGE;        //向上&向下都是边沿对齐
     timer_initpara.counterdirection  = TIMER_COUNTER_UP;
     timer_initpara.period             = 149;                    /* 自动重装载寄存器周期的值(计数值) */
     timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
     timer_initpara.repetitioncounter = 0;
     timer_init(TIMER4, &timer_initpara);


     timer_ocintpara.outputstate  = TIMER_CCX_ENABLE;
     timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE;
     timer_ocintpara.ocpolarity     = TIMER_OC_POLARITY_HIGH;
     timer_ocintpara.ocnpolarity  = TIMER_OCN_POLARITY_HIGH;
     timer_ocintpara.ocidlestate  = TIMER_OC_IDLE_STATE_LOW;
     timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
     timer_channel_output_config(TIMER4, TIMER_CH_2, &timer_ocintpara);
     timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_2, 50); //占空比 = TIMERx_CHxCV / TIMERx_CAR
     timer_channel_output_mode_config(TIMER4, TIMER_CH_2, TIMER_OC_MODE_PWM0);
     timer_channel_output_shadow_config(TIMER4, TIMER_CH_2, TIMER_OC_SHADOW_DISABLE);//TIMER_OC_SHADOW_ENABLE

     timer_primary_output_config(TIMER4,ENABLE);
     timer_auto_reload_shadow_enable(TIMER4);
                  
         // ////RGB0--(Timer4_Ch0)--(DMA0_ch2_stream6)-pa0
     dma_deinit(DMA0,DMA_CH0);

     /* initialize DMA single data mode */
     dma_data_parameter.periph_addr    = (uint32_t)(uint32_t)&TIMER_CH2CV(TIMER4); ;
     dma_data_parameter.periph_inc    = DMA_PERIPH_INCREASE_DISABLE;
     dma_data_parameter.memory0_addr = (uint32_t)LED_Buff;
     dma_data_parameter.memory_inc    = DMA_MEMORY_INCREASE_ENABLE;
     dma_data_parameter.periph_memory_width = DMA_PERIPH_WIDTH_32BIT;
     dma_data_parameter.direction    = DMA_MEMORY_TO_PERIPH;
     dma_data_parameter.number        = 42;
     dma_data_parameter.priority     = DMA_PRIORITY_HIGH;  

     dma_single_data_mode_init(DMA0, DMA_CH0, &dma_data_parameter);   
     dma_channel_subperipheral_select(DMA0, DMA_CH0, DMA_SUBPERI6);
     dma_circulation_disable(DMA0, DMA_CH0);
     timer_dma_enable(TIMER4,TIMER_DMA_UPD);
     dma_channel_disable(DMA0, DMA_CH0);
     timer_disable(TIMER4);                
}
  static void WS2812_send_internal(uint8_t (*color)[3], uint16_t len)
  {
      uint16_t buffersize = (len * 24) + 42;
      if(buffersize >= RGB_LEN) {
          return;
      }
      // 准备数据
      uint16_t memaddr = 0;
      for(uint16_t led = 0; led < len; led++) {
          // 准备RGB数据
          for(uint8_t j = 0; j < 8; j++) {
              LED_Buff[memaddr++] = ((color[led][1]<<j) & 0x80) ? RGB_LOGICAL_H : RGB_LOGICAL_L;
          }
          for(uint8_t j = 0; j < 8; j++) {
              LED_Buff[memaddr++] = ((color[led][0]<<j) & 0x80) ? RGB_LOGICAL_H : RGB_LOGICAL_L;
          }
          for(uint8_t j = 0; j < 8; j++) {
              LED_Buff[memaddr++] = ((color[led][2]<<j) & 0x80) ? RGB_LOGICAL_H : RGB_LOGICAL_L;
          }
      }     
      // 填充剩余缓冲区
      while(memaddr < buffersize) {
          LED_Buff[memaddr++] = 0;
      }            
          Tim4CH2_init_DMA(buffersize);
          dma_channel_enable(DMA0, DMA_CH0);
          timer_enable(TIMER4);     
  }
void WS2812_send(uint8_t (*color)[3], uint16_t len)
  {
      WS2812_send_internal(color, len);
  }

  // DMA中断处理函数
void DMA0_Channel0_IRQHandler(void)
{
      if(dma_flag_get(DMA0, DMA_CH0, DMA_INTF_FTFIF)) {
          dma_flag_clear(DMA0, DMA_CH0, DMA_INTF_FTFIF);          
                  dma_channel_disable(DMA0, DMA_CH0);
                  timer_disable(TIMER4);         
      }
}




void Tim4CH2_init_DMA(uint32_t number)
{
        dma_single_data_parameter_struct dma_data_parameter;

////RGB2-Timer4_Ch2--DMA0_ch0_stream6
     dma_deinit(DMA0,DMA_CH0);
     /* initialize DMA single data mode */
     dma_data_parameter.periph_addr    = (uint32_t)&TIMER_CH2CV(TIMER4);                  //DMA 目标地址:TIM4通道2的输出比较
     dma_data_parameter.periph_inc    = DMA_PERIPH_INCREASE_DISABLE;    //一个周期内地址是否自增
     dma_data_parameter.memory0_addr = (uint32_t)LED_Buff;      //DMA 源地址
     dma_data_parameter.memory_inc    = DMA_MEMORY_INCREASE_ENABLE;     //一个周期内地址是否自增
     dma_data_parameter.periph_memory_width = DMA_PERIPH_WIDTH_32BIT;  //设置DMA传输的位数
     dma_data_parameter.direction    = DMA_MEMORY_TO_PERIPH;           //DMA由内存向外设写入数据
     dma_data_parameter.number        = number;                         //DMA每次传输的数据长度
     dma_data_parameter.priority     = DMA_PRIORITY_HIGH;              //设置DMA的优先级

     dma_single_data_mode_init(DMA0, DMA_CH0, &dma_data_parameter);    //初始化DMA0的通道2
     dma_channel_subperipheral_select(DMA0, DMA_CH0, DMA_SUBPERI6);    //选择subperipheral
     dma_circulation_disable(DMA0, DMA_CH0);
     timer_dma_enable(TIMER4,TIMER_DMA_UPD);
     dma_channel_disable(DMA0, DMA_CH0);

     dma_interrupt_enable(DMA0, DMA_CH0, DMA_CHXCTL_FTFIE);
     nvic_irq_enable(DMA0_Channel0_IRQn, 2, 0);
}
int demo_test(void)
{
    Timer4_init();
    // 定义8个灯珠的RGB颜色(GRB顺序)
    uint8_t led_colors[3][3] = {
        {0xFF, 0xFF, 0x00}, //
        {0xFF, 0x00, 0x00}, //
        {0xFF, 0x00, 0xFF}, //
    };
    while (1) {
        // 发送数据(3个灯珠,使用Timer4_CH2通道)
      // WS2812_send(led_colors, 3);   
                WS2812_send(led_colors, 3);                
        delay_1ms(1000);      
    }
}





微信图片_20251211101146_89_23.png
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
120533
QQ
发表于 2025-12-11 10:45:34 | 显示全部楼层
先看下DMA的递减/递增次数计数器正常工作没
回复

使用道具 举报

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

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2026-1-12 07:21 , Processed in 0.055710 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表