打印

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

[复制链接]
963|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
我想使用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 | 只看该作者

使用特权

评论回复
5
YEHUANGLANG|  楼主 | 2023-8-13 18:56 | 只看该作者

使用特权

评论回复
6
YEHUANGLANG|  楼主 | 2023-8-13 18:57 | 只看该作者

使用特权

评论回复
7
YEHUANGLANG|  楼主 | 2023-8-13 18:58 | 只看该作者

使用特权

评论回复
8
YEHUANGLANG|  楼主 | 2023-8-13 18:58 | 只看该作者

使用特权

评论回复
9
YEHUANGLANG|  楼主 | 2023-8-13 18:59 | 只看该作者

使用特权

评论回复
10
renyaq| | 2023-8-13 19:16 | 只看该作者
看起来好痛苦

使用特权

评论回复
11
YEHUANGLANG|  楼主 | 2023-8-13 19:53 | 只看该作者

#include "gd32f1x0.h"
#include "systick.h"
#include "stdio.h"
#include "stdlib.h"

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


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

*******************************************************************************/
void delay(int time)
{
    while(time--);
   
    return;
}
void gpio_config(void)
{
    rcu_periph_clock_enable(RCU_GPIOB);//GPIOB时钟使能
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3);//PB3作为备用功能脚
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_3);//PB3配成输出

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

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

                gpio_bit_reset(GPIOB,GPIO_PIN_10);
    gpio_af_set(GPIOB, GPIO_AF_2, GPIO_PIN_3);//PB3功能选择TIMER1_CH1
    gpio_af_set(GPIOB, GPIO_AF_2, GPIO_PIN_10);
    gpio_af_set(GPIOB, GPIO_AF_2, GPIO_PIN_11);

}

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

    timer_channel_output_config(TIMER1, TIMER_CH_1, &timer_ocintpara);
    timer_channel_output_config(TIMER1, TIMER_CH_2, &timer_ocintpara);
    timer_channel_output_config(TIMER1, TIMER_CH_3, &timer_ocintpara);


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


    timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_2, 0);
    timer_channel_output_mode_config(TIMER1, TIMER_CH_2, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER1, TIMER_CH_2, TIMER_OC_SHADOW_ENABLE);


    timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_3, 0);
    timer_channel_output_mode_config(TIMER1, TIMER_CH_3, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER1, TIMER_CH_3, TIMER_OC_SHADOW_ENABLE);

                /*定时器主输出使能*/
                timer_primary_output_config(TIMER1, ENABLE);
                /*定时器1通道1 DMA请求使能*/
                timer_dma_enable(TIMER1, TIMER_DMA_CH1D);
    /* auto-reload preload enable */
   //timer_auto_reload_shadow_enable(TIMER1);//自动重装载影子比较器使能
                 timer_auto_reload_shadow_disable(TIMER1);//自动重装载影子比较器使能
    /* auto-reload preload enable */
    timer_enable(TIMER1);//定时器1使能
}

void dma_config(void)
{
        /*parameter:参数*/
        //dma_parameter_struct dma_struct;

/* 开启 DMA 时钟 */
rcu_periph_clock_enable(RCU_DMA);
/* DMA 初始化 */
dma_deinit(DMA_CH1);
        /*配置DMA*/
//外设基地址
dma_periph_address_config(DMA_CH1,(uint32_t)TIMER1_CH1CV_VALUE);
//外设传输数据宽度
dma_periph_width_config(DMA_CH1,DMA_PERIPHERAL_WIDTH_16BIT);       
//外设基地址增量禁止
dma_periph_increase_disable(DMA_CH1);       
//存储器基地址
dma_memory_address_config(DMA_CH1,(uint32_t)(&RGB_buffer));
//存储器传输数据宽度
dma_memory_width_config(DMA_CH1,DMA_PERIPHERAL_WIDTH_16BIT);
//存储器地址增量使能       
dma_memory_increase_enable(DMA_CH1);
//传输模式:存储器到外设
dma_transfer_direction_config(DMA_CH1,DMA_MEMORY_TO_PERIPHERAL);
//传输数据长度
dma_transfer_number_config(DMA_CH1,sizeof(RGB_buffer));
//DMA中断优先级为高
dma_priority_config(DMA_CH1,DMA_PRIORITY_MEDIUM);
//禁止循环模式
dma_circulation_disable(DMA_CH1);
//禁止存储器到存储器模式
dma_memory_to_memory_disable(DMA_CH1);
/* 使能 DMA 通道1 */
dma_channel_enable(DMA_CH1);
}

void setRGB(uint8_t red,uint8_t green,uint8_t blue)
{
                uint8_t i = 0,j =0;
                uint32_t rgb_value = green<<16 | red<<8 | blue;
                //while(dma_flag_get(DMA_CH1, DMA_INTF_FTFIF)==RESET);
                dma_flag_clear(DMA_CH1,DMA_INTFC_FTFIFC);
       
                dma_channel_disable(DMA_CH1);
       
                dma_transfer_number_config(DMA_CH1,sizeof(RGB_buffer));
                //timer_dma_transfer_config(TIMER1, TIMER_CH_1,TIMER_DMACFG_DMATA_CH1CV);
                for(j=1;j<=num;++j)
                {
                        for(i=0;i<24;++i)
                        {
                                if((rgb_value<<i)&0x800000) //高位先发,此时高位为1时
                                {
                                        RGB_buffer[i+45] = 7; //68%占空比
                                }
                                else
                                {
                                        RGB_buffer[i+45] = 3; //32%占空比
                                }
                        }
                }
               
                dma_channel_enable(DMA_CH1);

}
int main(void)
{
    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))
          systick_config();//配置1ms SysTick
    gpio_config();//PB3配置成定时器1通道1
          timer_config();
                delay_1ms(1);
    //timer_config();//800kHZ PWM波输出配置
                dma_config();
       
    while(1)
    {
                        setRGB(200,0,0);
    }

}

使用特权

评论回复
12
YEHUANGLANG|  楼主 | 2023-8-13 19:54 | 只看该作者
#include "gd32f1x0.h"
#include "systick.h"
#include "stdio.h"
#include "stdlib.h"

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


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

*******************************************************************************/
void delay(int time)
{
    while(time--);
   
    return;
}
void gpio_config(void)
{
    rcu_periph_clock_enable(RCU_GPIOB);//GPIOB时钟使能
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3);//PB3作为备用功能脚
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_3);//PB3配成输出

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

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

                gpio_bit_reset(GPIOB,GPIO_PIN_10);
    gpio_af_set(GPIOB, GPIO_AF_2, GPIO_PIN_3);//PB3功能选择TIMER1_CH1
    gpio_af_set(GPIOB, GPIO_AF_2, GPIO_PIN_10);
    gpio_af_set(GPIOB, GPIO_AF_2, GPIO_PIN_11);

}

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

    timer_channel_output_config(TIMER1, TIMER_CH_1, &timer_ocintpara);
    timer_channel_output_config(TIMER1, TIMER_CH_2, &timer_ocintpara);
    timer_channel_output_config(TIMER1, TIMER_CH_3, &timer_ocintpara);


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


    timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_2, 0);
    timer_channel_output_mode_config(TIMER1, TIMER_CH_2, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER1, TIMER_CH_2, TIMER_OC_SHADOW_ENABLE);


    timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_3, 0);
    timer_channel_output_mode_config(TIMER1, TIMER_CH_3, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER1, TIMER_CH_3, TIMER_OC_SHADOW_ENABLE);

                /*定时器主输出使能*/
                timer_primary_output_config(TIMER1, ENABLE);
                /*定时器1通道1 DMA请求使能*/
                timer_dma_enable(TIMER1, TIMER_DMA_CH1D);
    /* auto-reload preload enable */
   //timer_auto_reload_shadow_enable(TIMER1);//自动重装载影子比较器使能
                 timer_auto_reload_shadow_disable(TIMER1);//自动重装载影子比较器使能
    /* auto-reload preload enable */
    timer_enable(TIMER1);//定时器1使能
}

void dma_config(void)
{
        /*parameter:参数*/
        //dma_parameter_struct dma_struct;

/* 开启 DMA 时钟 */
rcu_periph_clock_enable(RCU_DMA);
/* DMA 初始化 */
dma_deinit(DMA_CH1);
        /*配置DMA*/
//外设基地址
dma_periph_address_config(DMA_CH1,(uint32_t)TIMER1_CH1CV_VALUE);
//外设传输数据宽度
dma_periph_width_config(DMA_CH1,DMA_PERIPHERAL_WIDTH_16BIT);       
//外设基地址增量禁止
dma_periph_increase_disable(DMA_CH1);       
//存储器基地址
dma_memory_address_config(DMA_CH1,(uint32_t)(&RGB_buffer));
//存储器传输数据宽度
dma_memory_width_config(DMA_CH1,DMA_PERIPHERAL_WIDTH_16BIT);
//存储器地址增量使能       
dma_memory_increase_enable(DMA_CH1);
//传输模式:存储器到外设
dma_transfer_direction_config(DMA_CH1,DMA_MEMORY_TO_PERIPHERAL);
//传输数据长度
dma_transfer_number_config(DMA_CH1,sizeof(RGB_buffer));
//DMA中断优先级为高
dma_priority_config(DMA_CH1,DMA_PRIORITY_MEDIUM);
//禁止循环模式
dma_circulation_disable(DMA_CH1);
//禁止存储器到存储器模式
dma_memory_to_memory_disable(DMA_CH1);
/* 使能 DMA 通道1 */
dma_channel_enable(DMA_CH1);
}

void setRGB(uint8_t red,uint8_t green,uint8_t blue)
{
                uint8_t i = 0,j =0;
                uint32_t rgb_value = green<<16 | red<<8 | blue;
                //while(dma_flag_get(DMA_CH1, DMA_INTF_FTFIF)==RESET);
                dma_flag_clear(DMA_CH1,DMA_INTFC_FTFIFC);
       
                dma_channel_disable(DMA_CH1);
       
                dma_transfer_number_config(DMA_CH1,sizeof(RGB_buffer));
                //timer_dma_transfer_config(TIMER1, TIMER_CH_1,TIMER_DMACFG_DMATA_CH1CV);
                for(j=1;j<=num;++j)
                {
                        for(i=0;i<24;++i)
                        {
                                if((rgb_value<<i)&0x800000) //高位先发,此时高位为1时
                                {
                                        RGB_buffer[i+45] = 7; //68%占空比
                                }
                                else
                                {
                                        RGB_buffer[i+45] = 3; //32%占空比
                                }
                        }
                }
               
                dma_channel_enable(DMA_CH1);

}
int main(void)
{
    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))
          systick_config();//配置1ms SysTick
    gpio_config();//PB3配置成定时器1通道1
          timer_config();
                delay_1ms(1);
    //timer_config();//800kHZ PWM波输出配置
                dma_config();
       
    while(1)
    {
                        setRGB(200,0,0);
    }

}

使用特权

评论回复
13
coody| | 2023-8-14 11:43 | 只看该作者
2812建议用SPI+DMA控制。

使用特权

评论回复
14
Addition| | 2023-8-14 17:52 | 只看该作者
确定一下DMA可以正常发送了吗?

使用特权

评论回复
15
dengdc| | 2023-8-14 19:52 | 只看该作者
C:\Users\Administrator\Desktop\新建文件夹 (2)
这是啥?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

16

主题

56

帖子

1

粉丝