GD32F130使用定时器产生PWM+DMA控制WS2812

[复制链接]
1429|14
 楼主| YEHUANGLANG 发表于 2023-8-13 18:51 | 显示全部楼层 |阅读模式
我想使用130定时器1控制WS2812,但是怎么都没有波形,如果把占空比设置成一个数,可以产生固定占空比的波形,感觉是占空比没有更新,但是又不知道哪里没有更新,有没有大佬用过?C:\Users\Administrator\Desktop\新建文件夹 (2)
 楼主| YEHUANGLANG 发表于 2023-8-13 18:52 | 显示全部楼层
 楼主| YEHUANGLANG 发表于 2023-8-13 18:53 | 显示全部楼层
 楼主| YEHUANGLANG 发表于 2023-8-13 18:55 | 显示全部楼层
 楼主| YEHUANGLANG 发表于 2023-8-13 18:56 | 显示全部楼层
 楼主| YEHUANGLANG 发表于 2023-8-13 18:57 | 显示全部楼层
 楼主| YEHUANGLANG 发表于 2023-8-13 18:58 | 显示全部楼层
 楼主| YEHUANGLANG 发表于 2023-8-13 18:58 | 显示全部楼层
 楼主| YEHUANGLANG 发表于 2023-8-13 18:59 | 显示全部楼层
renyaq 发表于 2023-8-13 19:16 | 显示全部楼层
看起来好痛苦
 楼主| YEHUANGLANG 发表于 2023-8-13 19:53 | 显示全部楼层

  1. #include "gd32f1x0.h"
  2. #include "systick.h"
  3. #include "stdio.h"
  4. #include "stdlib.h"

  5. #define num 4
  6. #define TIMER1_CH1CV_VALUE (0x40000038U)
  7. uint16_t RGB_buffer[45+num*24]={0};


  8. /*****************************************************************************
  9.   文件: main.c
  10.   作者: Zhengyu https://gzwelink.taobao.com
  11.   版本: V1.0.0
  12.   时间: 20210401
  13.         平台:MINI-GD32F130C8T6开发板
  14.         微信号:gzwelink

  15. *******************************************************************************/
  16. void delay(int time)
  17. {
  18.     while(time--);
  19.    
  20.     return;
  21. }
  22. void gpio_config(void)
  23. {
  24.     rcu_periph_clock_enable(RCU_GPIOB);//GPIOB时钟使能
  25.     gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3);//PB3作为备用功能脚
  26.     gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_3);//PB3配成输出

  27.     gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
  28.     gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10);

  29.     gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
  30.     gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_11);

  31.                 gpio_bit_reset(GPIOB,GPIO_PIN_10);
  32.     gpio_af_set(GPIOB, GPIO_AF_2, GPIO_PIN_3);//PB3功能选择TIMER1_CH1
  33.     gpio_af_set(GPIOB, GPIO_AF_2, GPIO_PIN_10);
  34.     gpio_af_set(GPIOB, GPIO_AF_2, GPIO_PIN_11);

  35. }

  36. void timer_config(void)
  37. {
  38.     /* -----------------------------------------------------------------------
  39.     TIMER1 配置:产生3个不同的PWM信号:
  40.     TIMER1CLK = SystemCoreClock / 6*10 = 8KHz
  41.     TIMER1 channel 2 duty cycle =  50%
  42.     ----------------------------------------------------------------------- */
  43.     /*定时器输出通道参数设置结构体*/
  44.                 timer_oc_parameter_struct timer_ocintpara;
  45.                 /*定时器参数设置结构体*/
  46.     timer_parameter_struct timer_initpara;
  47.                 //开启定时器1时钟
  48.     rcu_periph_clock_enable(RCU_TIMER1);
  49.                 //定时器1初始化
  50.     timer_deinit(TIMER1);
  51.     ///////////////////////////////以下配置成定时器1.25us,PWM就是800KHZ  48M/6*10///////////////////////////
  52.     /* TIMER1 configuration */
  53.     timer_initpara.prescaler         = 5;    //预分频值
  54.     timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;//对齐模式:边沿对齐
  55.     timer_initpara.counterdirection  = TIMER_COUNTER_UP;//技术模式:向上计数
  56.     timer_initpara.period            = 9;//计数值
  57.     timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;  //时钟分频值1
  58.     timer_initpara.repetitioncounter = 0; //计数器重赋值0
  59.                 //配置定时器1
  60.     timer_init(TIMER1,&timer_initpara);
  61.     /////////////////////////////////////////////////////////////////////////////////////////////////////////
  62.     /* CH1, CH2 and CH3 configuration in PWM0 mode */
  63.     timer_ocintpara.ocpolarity  = TIMER_OC_POLARITY_HIGH;//通道输出极性高
  64.                 timer_ocintpara.ocnpolarity  = TIMER_OCN_POLARITY_HIGH;//通道输出互补极性高
  65.     timer_ocintpara.outputstate = TIMER_CCX_ENABLE;  //通道输出状态使能
  66.                 timer_ocintpara.outputnstate = TIMER_CCXN_ENABLE;  //通道互补使能
  67.                 timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_HIGH;//通道输出的空闲状态为高
  68.                 timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; //通道互补输出的空闲状态为低

  69.     timer_channel_output_config(TIMER1, TIMER_CH_1, &timer_ocintpara);
  70.     timer_channel_output_config(TIMER1, TIMER_CH_2, &timer_ocintpara);
  71.     timer_channel_output_config(TIMER1, TIMER_CH_3, &timer_ocintpara);


  72.     timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, 0);//配置定时器1通道1 PWM 占空比
  73.     timer_channel_output_mode_config(TIMER1, TIMER_CH_1, TIMER_OC_MODE_PWM0);
  74.     timer_channel_output_shadow_config(TIMER1, TIMER_CH_1, TIMER_OC_SHADOW_ENABLE);


  75.     timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_2, 0);
  76.     timer_channel_output_mode_config(TIMER1, TIMER_CH_2, TIMER_OC_MODE_PWM0);
  77.     timer_channel_output_shadow_config(TIMER1, TIMER_CH_2, TIMER_OC_SHADOW_ENABLE);


  78.     timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_3, 0);
  79.     timer_channel_output_mode_config(TIMER1, TIMER_CH_3, TIMER_OC_MODE_PWM0);
  80.     timer_channel_output_shadow_config(TIMER1, TIMER_CH_3, TIMER_OC_SHADOW_ENABLE);

  81.                 /*定时器主输出使能*/
  82.                 timer_primary_output_config(TIMER1, ENABLE);
  83.                 /*定时器1通道1 DMA请求使能*/
  84.                 timer_dma_enable(TIMER1, TIMER_DMA_CH1D);
  85.     /* auto-reload preload enable */
  86.    //timer_auto_reload_shadow_enable(TIMER1);//自动重装载影子比较器使能
  87.                  timer_auto_reload_shadow_disable(TIMER1);//自动重装载影子比较器使能
  88.     /* auto-reload preload enable */
  89.     timer_enable(TIMER1);//定时器1使能
  90. }

  91. void dma_config(void)
  92. {
  93.         /*parameter:参数*/
  94.         //dma_parameter_struct dma_struct;

  95. /* 开启 DMA 时钟 */
  96. rcu_periph_clock_enable(RCU_DMA);
  97. /* DMA 初始化 */
  98. dma_deinit(DMA_CH1);
  99.         /*配置DMA*/
  100. //外设基地址
  101. dma_periph_address_config(DMA_CH1,(uint32_t)TIMER1_CH1CV_VALUE);
  102. //外设传输数据宽度
  103. dma_periph_width_config(DMA_CH1,DMA_PERIPHERAL_WIDTH_16BIT);       
  104. //外设基地址增量禁止
  105. dma_periph_increase_disable(DMA_CH1);       
  106. //存储器基地址
  107. dma_memory_address_config(DMA_CH1,(uint32_t)(&RGB_buffer));
  108. //存储器传输数据宽度
  109. dma_memory_width_config(DMA_CH1,DMA_PERIPHERAL_WIDTH_16BIT);
  110. //存储器地址增量使能       
  111. dma_memory_increase_enable(DMA_CH1);
  112. //传输模式:存储器到外设
  113. dma_transfer_direction_config(DMA_CH1,DMA_MEMORY_TO_PERIPHERAL);
  114. //传输数据长度
  115. dma_transfer_number_config(DMA_CH1,sizeof(RGB_buffer));
  116. //DMA中断优先级为高
  117. dma_priority_config(DMA_CH1,DMA_PRIORITY_MEDIUM);
  118. //禁止循环模式
  119. dma_circulation_disable(DMA_CH1);
  120. //禁止存储器到存储器模式
  121. dma_memory_to_memory_disable(DMA_CH1);
  122. /* 使能 DMA 通道1 */
  123. dma_channel_enable(DMA_CH1);
  124. }

  125. void setRGB(uint8_t red,uint8_t green,uint8_t blue)
  126. {
  127.                 uint8_t i = 0,j =0;
  128.                 uint32_t rgb_value = green<<16 | red<<8 | blue;
  129.                 //while(dma_flag_get(DMA_CH1, DMA_INTF_FTFIF)==RESET);
  130.                 dma_flag_clear(DMA_CH1,DMA_INTFC_FTFIFC);
  131.        
  132.                 dma_channel_disable(DMA_CH1);
  133.        
  134.                 dma_transfer_number_config(DMA_CH1,sizeof(RGB_buffer));
  135.                 //timer_dma_transfer_config(TIMER1, TIMER_CH_1,TIMER_DMACFG_DMATA_CH1CV);
  136.                 for(j=1;j<=num;++j)
  137.                 {
  138.                         for(i=0;i<24;++i)
  139.                         {
  140.                                 if((rgb_value<<i)&0x800000) //高位先发,此时高位为1时
  141.                                 {
  142.                                         RGB_buffer[i+45] = 7; //68%占空比
  143.                                 }
  144.                                 else
  145.                                 {
  146.                                         RGB_buffer[i+45] = 3; //32%占空比
  147.                                 }
  148.                         }
  149.                 }
  150.                
  151.                 dma_channel_enable(DMA_CH1);

  152. }
  153. int main(void)
  154. {
  155.     rcu_ahb_clock_config(RCU_AHB_CKSYS_DIV1);//设置主频48M(#define __SYSTEM_CLOCK_72M_PLL_HXTAL         (uint32_t)(72000000)),8M外部晶振  (#define HXTAL_VALUE    ((uint32_t)8000000))
  156.           systick_config();//配置1ms SysTick
  157.     gpio_config();//PB3配置成定时器1通道1
  158.           timer_config();
  159.                 delay_1ms(1);
  160.     //timer_config();//800kHZ PWM波输出配置
  161.                 dma_config();
  162.        
  163.     while(1)
  164.     {
  165.                         setRGB(200,0,0);
  166.     }

  167. }
 楼主| YEHUANGLANG 发表于 2023-8-13 19:54 | 显示全部楼层
  1. #include "gd32f1x0.h"
  2. #include "systick.h"
  3. #include "stdio.h"
  4. #include "stdlib.h"

  5. #define num 4
  6. #define TIMER1_CH1CV_VALUE (0x40000038U)
  7. uint16_t RGB_buffer[45+num*24]={0};


  8. /*****************************************************************************
  9.   文件: main.c
  10.   作者: Zhengyu https://gzwelink.taobao.com
  11.   版本: V1.0.0
  12.   时间: 20210401
  13.         平台:MINI-GD32F130C8T6开发板
  14.         微信号:gzwelink

  15. *******************************************************************************/
  16. void delay(int time)
  17. {
  18.     while(time--);
  19.    
  20.     return;
  21. }
  22. void gpio_config(void)
  23. {
  24.     rcu_periph_clock_enable(RCU_GPIOB);//GPIOB时钟使能
  25.     gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3);//PB3作为备用功能脚
  26.     gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_3);//PB3配成输出

  27.     gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
  28.     gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10);

  29.     gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
  30.     gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_11);

  31.                 gpio_bit_reset(GPIOB,GPIO_PIN_10);
  32.     gpio_af_set(GPIOB, GPIO_AF_2, GPIO_PIN_3);//PB3功能选择TIMER1_CH1
  33.     gpio_af_set(GPIOB, GPIO_AF_2, GPIO_PIN_10);
  34.     gpio_af_set(GPIOB, GPIO_AF_2, GPIO_PIN_11);

  35. }

  36. void timer_config(void)
  37. {
  38.     /* -----------------------------------------------------------------------
  39.     TIMER1 配置:产生3个不同的PWM信号:
  40.     TIMER1CLK = SystemCoreClock / 6*10 = 8KHz
  41.     TIMER1 channel 2 duty cycle =  50%
  42.     ----------------------------------------------------------------------- */
  43.     /*定时器输出通道参数设置结构体*/
  44.                 timer_oc_parameter_struct timer_ocintpara;
  45.                 /*定时器参数设置结构体*/
  46.     timer_parameter_struct timer_initpara;
  47.                 //开启定时器1时钟
  48.     rcu_periph_clock_enable(RCU_TIMER1);
  49.                 //定时器1初始化
  50.     timer_deinit(TIMER1);
  51.     ///////////////////////////////以下配置成定时器1.25us,PWM就是800KHZ  48M/6*10///////////////////////////
  52.     /* TIMER1 configuration */
  53.     timer_initpara.prescaler         = 5;    //预分频值
  54.     timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;//对齐模式:边沿对齐
  55.     timer_initpara.counterdirection  = TIMER_COUNTER_UP;//技术模式:向上计数
  56.     timer_initpara.period            = 9;//计数值
  57.     timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;  //时钟分频值1
  58.     timer_initpara.repetitioncounter = 0; //计数器重赋值0
  59.                 //配置定时器1
  60.     timer_init(TIMER1,&timer_initpara);
  61.     /////////////////////////////////////////////////////////////////////////////////////////////////////////
  62.     /* CH1, CH2 and CH3 configuration in PWM0 mode */
  63.     timer_ocintpara.ocpolarity  = TIMER_OC_POLARITY_HIGH;//通道输出极性高
  64.                 timer_ocintpara.ocnpolarity  = TIMER_OCN_POLARITY_HIGH;//通道输出互补极性高
  65.     timer_ocintpara.outputstate = TIMER_CCX_ENABLE;  //通道输出状态使能
  66.                 timer_ocintpara.outputnstate = TIMER_CCXN_ENABLE;  //通道互补使能
  67.                 timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_HIGH;//通道输出的空闲状态为高
  68.                 timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; //通道互补输出的空闲状态为低

  69.     timer_channel_output_config(TIMER1, TIMER_CH_1, &timer_ocintpara);
  70.     timer_channel_output_config(TIMER1, TIMER_CH_2, &timer_ocintpara);
  71.     timer_channel_output_config(TIMER1, TIMER_CH_3, &timer_ocintpara);


  72.     timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, 0);//配置定时器1通道1 PWM 占空比
  73.     timer_channel_output_mode_config(TIMER1, TIMER_CH_1, TIMER_OC_MODE_PWM0);
  74.     timer_channel_output_shadow_config(TIMER1, TIMER_CH_1, TIMER_OC_SHADOW_ENABLE);


  75.     timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_2, 0);
  76.     timer_channel_output_mode_config(TIMER1, TIMER_CH_2, TIMER_OC_MODE_PWM0);
  77.     timer_channel_output_shadow_config(TIMER1, TIMER_CH_2, TIMER_OC_SHADOW_ENABLE);


  78.     timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_3, 0);
  79.     timer_channel_output_mode_config(TIMER1, TIMER_CH_3, TIMER_OC_MODE_PWM0);
  80.     timer_channel_output_shadow_config(TIMER1, TIMER_CH_3, TIMER_OC_SHADOW_ENABLE);

  81.                 /*定时器主输出使能*/
  82.                 timer_primary_output_config(TIMER1, ENABLE);
  83.                 /*定时器1通道1 DMA请求使能*/
  84.                 timer_dma_enable(TIMER1, TIMER_DMA_CH1D);
  85.     /* auto-reload preload enable */
  86.    //timer_auto_reload_shadow_enable(TIMER1);//自动重装载影子比较器使能
  87.                  timer_auto_reload_shadow_disable(TIMER1);//自动重装载影子比较器使能
  88.     /* auto-reload preload enable */
  89.     timer_enable(TIMER1);//定时器1使能
  90. }

  91. void dma_config(void)
  92. {
  93.         /*parameter:参数*/
  94.         //dma_parameter_struct dma_struct;

  95. /* 开启 DMA 时钟 */
  96. rcu_periph_clock_enable(RCU_DMA);
  97. /* DMA 初始化 */
  98. dma_deinit(DMA_CH1);
  99.         /*配置DMA*/
  100. //外设基地址
  101. dma_periph_address_config(DMA_CH1,(uint32_t)TIMER1_CH1CV_VALUE);
  102. //外设传输数据宽度
  103. dma_periph_width_config(DMA_CH1,DMA_PERIPHERAL_WIDTH_16BIT);       
  104. //外设基地址增量禁止
  105. dma_periph_increase_disable(DMA_CH1);       
  106. //存储器基地址
  107. dma_memory_address_config(DMA_CH1,(uint32_t)(&RGB_buffer));
  108. //存储器传输数据宽度
  109. dma_memory_width_config(DMA_CH1,DMA_PERIPHERAL_WIDTH_16BIT);
  110. //存储器地址增量使能       
  111. dma_memory_increase_enable(DMA_CH1);
  112. //传输模式:存储器到外设
  113. dma_transfer_direction_config(DMA_CH1,DMA_MEMORY_TO_PERIPHERAL);
  114. //传输数据长度
  115. dma_transfer_number_config(DMA_CH1,sizeof(RGB_buffer));
  116. //DMA中断优先级为高
  117. dma_priority_config(DMA_CH1,DMA_PRIORITY_MEDIUM);
  118. //禁止循环模式
  119. dma_circulation_disable(DMA_CH1);
  120. //禁止存储器到存储器模式
  121. dma_memory_to_memory_disable(DMA_CH1);
  122. /* 使能 DMA 通道1 */
  123. dma_channel_enable(DMA_CH1);
  124. }

  125. void setRGB(uint8_t red,uint8_t green,uint8_t blue)
  126. {
  127.                 uint8_t i = 0,j =0;
  128.                 uint32_t rgb_value = green<<16 | red<<8 | blue;
  129.                 //while(dma_flag_get(DMA_CH1, DMA_INTF_FTFIF)==RESET);
  130.                 dma_flag_clear(DMA_CH1,DMA_INTFC_FTFIFC);
  131.        
  132.                 dma_channel_disable(DMA_CH1);
  133.        
  134.                 dma_transfer_number_config(DMA_CH1,sizeof(RGB_buffer));
  135.                 //timer_dma_transfer_config(TIMER1, TIMER_CH_1,TIMER_DMACFG_DMATA_CH1CV);
  136.                 for(j=1;j<=num;++j)
  137.                 {
  138.                         for(i=0;i<24;++i)
  139.                         {
  140.                                 if((rgb_value<<i)&0x800000) //高位先发,此时高位为1时
  141.                                 {
  142.                                         RGB_buffer[i+45] = 7; //68%占空比
  143.                                 }
  144.                                 else
  145.                                 {
  146.                                         RGB_buffer[i+45] = 3; //32%占空比
  147.                                 }
  148.                         }
  149.                 }
  150.                
  151.                 dma_channel_enable(DMA_CH1);

  152. }
  153. int main(void)
  154. {
  155.     rcu_ahb_clock_config(RCU_AHB_CKSYS_DIV1);//设置主频48M(#define __SYSTEM_CLOCK_72M_PLL_HXTAL         (uint32_t)(72000000)),8M外部晶振  (#define HXTAL_VALUE    ((uint32_t)8000000))
  156.           systick_config();//配置1ms SysTick
  157.     gpio_config();//PB3配置成定时器1通道1
  158.           timer_config();
  159.                 delay_1ms(1);
  160.     //timer_config();//800kHZ PWM波输出配置
  161.                 dma_config();
  162.        
  163.     while(1)
  164.     {
  165.                         setRGB(200,0,0);
  166.     }

  167. }
coody 发表于 2023-8-14 11:43 | 显示全部楼层
2812建议用SPI+DMA控制。
Addition 发表于 2023-8-14 17:52 | 显示全部楼层
确定一下DMA可以正常发送了吗?
dengdc 发表于 2023-8-14 19:52 | 显示全部楼层
C:\Users\Administrator\Desktop\新建文件夹 (2)
这是啥?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

16

主题

56

帖子

1

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