问答

汇集网友智慧,解决技术难题

21ic问答首页 - 为什么我的 PWM DMA 不起作用 是那里配置错了吗

DMA PWM timer TI IO

为什么我的 PWM DMA 不起作用 是那里配置错了吗

sadasdafaffg2025-12-10
这是代码  DMA一直没更新成功 buf

#include "bsp_pwm.h"

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


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

     /* TIMER1 channel3 configuration in PWM mode */
     timer_ocintpara.outputstate  = TIMER_CCX_ENABLE;
       
     timer_ocintpara.ocpolarity     = TIMER_OC_POLARITY_HIGH;
     timer_channel_output_config(TIMER4, TIMER_CH_2, &timer_ocintpara);

     timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_2, 500); //占空比 = 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_auto_reload_shadow_disable(TIMER4);
//        timer_dma_transfer_config
//        timer_dma_enable(TIMER4,TIMER_DMA_UPD);
//        timer_disable(TIMER4);

    timer_primary_output_config(TIMER4,ENABLE);

    timer_dma_enable(TIMER4,TIMER_DMA_UPD);/*此处选择定时器更新事件*/

    timer_auto_reload_shadow_enable(TIMER4);

    timer_enable(TIMER4);


}
  

  static void WS2812_send_internal(uint8_t (*color)[3], uint16_t len, uint8_t PWM_CHANNEL)
  {
      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, uint8_t PWM_CHANNEL)
  {
      WS2812_send_internal(color, len, PWM_CHANNEL);
  }
  
void rgb_dma_complete_callback(uint8_t channel)
{        
         dma_channel_disable(DMA0, DMA_CH0);
         timer_disable(TIMER4);      
     // rgb_state.is_refreshing = false;
  }
  
  // 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);
          // 由于DMA2被通道0和2共享,我们需要知道当前是哪个通道在使用
          // 这里我们假设通道0和2是交替使用的      
           //  rgb_dma_complete_callback(0);                  
                    dma_channel_disable(DMA0, DMA_CH0);
                        timer_disable(TIMER4);         
      }
}
void Tim4CH2_init_DMA(uint32_t number)
{
     dma_single_data_parameter_struct dma_data_parameter;
         
     rcu_periph_clock_enable(RCU_DMA0);   
     dma_deinit(DMA0,DMA_CH0);
     
     /* initialize DMA single data mode */
     dma_data_parameter.periph_addr    = (uint32_t)TIMER4_CH2CV;//(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        = number;
     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_SUBPERI5);
     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);
         
         dma_channel_enable(DMA0, DMA_CH0); //
    /* enable DMA channel5 */
//   dma_channel_enable(DMA0,DMA_CH5);         
}

int demo_test(void)
{
    Timer4_init();
    // 定义8个灯珠的RGB颜色(GRB顺序)
    uint8_t led_colors[3][3] = {
        {0x00, 0xFF, 0x00}, // 绿色 (G=0, R=255, B=0) -> 实际显示为绿色
        {0xFF, 0x00, 0x00}, // 红色
        {0x00, 0x00, 0xFF}, // 蓝色
    };
    // 无限循环:交替显示颜色
    while (1) {
        // 发送数据(8个灯珠,使用Timer2_CH3通道)
       WS2812_send(led_colors, 3, 0);           
        delay_1ms(1000);      
    }
}



回答 +关注 0
384人浏览 0人回答问题 分享 举报
0 个回答

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