GD32F427,GD32F4XX,定时器0互补输出PWM

下面分享GD32F427,基于GD官方库,控制TIMER0 的PWM通道channel0,channel0N和channel2输出PWM,其中channel0和channel0N为互补输出PWM。

本工程中SSysClock为120M。先初始化时钟。初始化完后Get 一下时钟是否正确,APB时钟是否符合datasheet要求。

    SysClk = rcu_clock_freq_get(CK_SYS);  //120M 
    HClk = rcu_clock_freq_get(CK_AHB);    //120M
    PClk1 = rcu_clock_freq_get(CK_APB1);   //30M
    PClk2 = rcu_clock_freq_get(CK_APB2);   //60M

IO初始化:涉及的IO是PE8,PE9,PE12,分别是TIMER0_C H0_ON,TIMER0_C H0,TIMER0_C H2_ON。

datasheet如下:

    rcu_periph_clock_enable(RCU_GPIOE);
    
    gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE,GPIO_PIN_8);
    gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_8);
    gpio_af_set(GPIOE, GPIO_AF_1,GPIO_PIN_8); 
    
    gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE,GPIO_PIN_9);
    gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_9);
    gpio_af_set(GPIOE, GPIO_AF_1,GPIO_PIN_9);
   
    gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE,GPIO_PIN_12);
    gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_12);
    gpio_af_set(GPIOE, GPIO_AF_1,GPIO_PIN_12); 

下面分享PWM参数。本例输出PWM的频率为40K,互补输出的占空比带死区控制,分频psc和period计算按公式:

PWM周期T = (1+psc)*(1+period)/(SysClock*CLK_DIV);

SysClock 也就是定时器时钟,倍频为到120M,CLK_DIV为分频系数,默认选TIMER_CKDIV_DIV1。

然后是Channel0和Channel0N的输出配置,关注timer_ocintpara 结构体即可。设置通道是否输出,输出极性,空闲状态极性等参数。

然后设置输出的占空比,占空比是比值,参数除period即可得占空比,实际应用中根据需要的占空比倒推出分子即可。

然后设置PWM输出模式和影子设置。

然后是死区设置,死区时间计算:代码如下:

uint8_t deadtime(uint8_t pwmfre_KHz,uint8_t myCLK_MHz, uint8_t mydutyc)
{
    float T_TDS;
    T_TDS = (float)1000 / myCLK_MHz; //   1000/60 = 16.6666   1000/48 = 20.8333

    float DT;//死区时间
    DT = (50 - mydutyc) *10000 / pwmfre_KHz; // (50-20)*10000/40 =  7500

    uint8_t dt;
    if ( DT >= 0 && DT <= T_TDS * 127)  //16.666 *127 = 2116     
    {
        dt = (uint8_t)(DT / T_TDS);

    }
    else if ( DT >= T_TDS * 128 && DT <= T_TDS * 254) //16.666 *128 = 2133.338   16.666 *254=4233  
    {
        dt = (uint8_t)(DT / (2 * T_TDS) + 64 );

    }
    else if ( DT >= T_TDS * 256 && DT <= T_TDS * 504) //16.666 *256= 4266   16.666 *504 = 8400  ,20.8333333*256=5,333.3333248  , 20.8333333*504=10499
    {
        dt = (uint8_t)(DT / (8 * T_TDS) + 160 );     // 216,     205
 
    }
    else 
    {
        dt = (uint8_t)(DT / (16 * T_TDS) + 192 );

    }
    return dt;
}

按照输出40Khz PWM脉冲,120M系统时钟,20%占空比,死区计算时间函数为:

deadtime = deadtime(40,120,20);

定时器初始化以及PWM参数初始化代码如下,上代码:

void Drv_PWM_TimerConfig(void)
{
    timer_oc_parameter_struct timer_ocintpara;
    timer_parameter_struct timer_initpara;
    timer_break_parameter_struct timer_breakpara;

    rcu_periph_clock_enable(RCU_TIMER0);
    rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);

    timer_deinit(TIMER0);

    /* TIMER0 configuration */
    timer_initpara.prescaler         = 3-1;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 1000-1;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER0,&timer_initpara);

    /* CH0/CH0N configuration in PWM mode0 */
    timer_ocintpara.outputstate  = TIMER_CCX_ENABLE;
    timer_ocintpara.outputnstate = TIMER_CCXN_ENABLE;
    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(TIMER0,TIMER_CH_0,&timer_ocintpara);
    
    timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_0, 500);  
    timer_channel_output_mode_config(TIMER0,TIMER_CH_0,TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER0,TIMER_CH_0,TIMER_OC_SHADOW_DISABLE);
 
    /* automatic output enable, break, dead time and lock configuration*/
    timer_breakpara.runoffstate      = TIMER_ROS_STATE_ENABLE;//TIMER_ROS_STATE_DISABLE
    timer_breakpara.ideloffstate     = TIMER_IOS_STATE_ENABLE;//TIMER_IOS_STATE_DISABLE
    timer_breakpara.deadtime         = 216;  //216
    timer_breakpara.breakpolarity    = TIMER_BREAK_POLARITY_HIGH;
    timer_breakpara.outputautostate  = TIMER_OUTAUTO_ENABLE;
    timer_breakpara.protectmode      = TIMER_CCHP_PROT_0;
    timer_breakpara.breakstate       = TIMER_BREAK_DISABLE;  //TIMER_BREAK_ENABLE
    timer_break_config(TIMER0,&timer_breakpara);

        /*channel 2 pwm output*/
    timer_ocintpara.outputstate  = TIMER_CCX_DISABLE;  //  TIMER_CCX_ENABLE
    timer_ocintpara.outputnstate = TIMER_CCXN_ENABLE; //  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_OC_IDLE_STATE_HIGH
    timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;   //TIMER_OCN_IDLE_STATE_LOW
    timer_channel_output_config(TIMER0,TIMER_CH_2,&timer_ocintpara);
    timer_channel_output_mode_config(TIMER0,TIMER_CH_2,TIMER_OC_MODE_PWM0);
 
    timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_2, 500);   
    timer_channel_output_mode_config(TIMER0,TIMER_CH_2,TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER0,TIMER_CH_2,TIMER_OC_SHADOW_DISABLE);    
    /* TIMER0 primary output function enable */
    timer_primary_output_config(TIMER0,ENABLE);

    /* auto-reload preload enable */
    timer_auto_reload_shadow_enable(TIMER0);

    /* TIMER0 counter enable */
    timer_enable(TIMER0);
    
}

特别注意的是,GD官方库的例程,比如互补输出或者死区控制的,有的参数并不对,比如

    timer_breakpara.runoffstate      = TIMER_ROS_STATE_ENABLE;//TIMER_ROS_STATE_DISABLE
    timer_breakpara.ideloffstate     = TIMER_IOS_STATE_ENABLE;//TIMER_IOS_STATE_DISABLE
    timer_breakpara.deadtime         = 216;  //216
    timer_breakpara.breakpolarity    = TIMER_BREAK_POLARITY_HIGH;
    timer_breakpara.outputautostate  = TIMER_OUTAUTO_ENABLE;
    timer_breakpara.protectmode      = TIMER_CCHP_PROT_0;
    timer_breakpara.breakstate       = TIMER_BREAK_DISABLE;  //TIMER_BREAK_ENABLE
    timer_break_config(TIMER0,&timer_breakpara);

里的runoffstate      ,ideloffstate     ,breakstate       ,这些,官方demo里的 是我注释后的参数,并不能正常输出,导致我排查问题找了接近两天,然后对比ST库的函数和参数,才改正过来,才能正常输出。好了 下面上波形。

Channel0 是PE8的输出

Channel1是PE9 的输出

Channel2是PE12的输出

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
GD32F303定时器互补PWM功能是通过配置定时器的通道来实现的。在使用互补PWM之前,需要先进行一些初始化配置。 首先,根据引用中提到的,确保你已经有一个包含GD32F303标准库的Keil工程。 接下来,根据引用中提到的,你需要配置定时器的时钟。通过使能所需的外设时钟来配置时钟。具体的时钟配置函数可以参考官方例程或者手册。 然后,你需要配置定时器的工作模式和周期。根据你的需求选择合适的定时器和通道。可以参考引用中提到的官方手册来了解各个定时器的功能和特点。 在配置互补PWM之前,你需要配置定时器的通道模式为PWM输出模式,并设置占空比。 最后,通过设置定时器互补输出使能和互补输出极性来启用互补PWM。 总结起来,配置GD32F303定时器互补PWM功能的步骤如下: 1. 确保你有一个包含GD32F303标准库的Keil工程。 2. 配置定时器的时钟,使能所需的外设时钟。 3. 根据需求选择合适的定时器和通道,并配置工作模式和周期。 4. 配置定时器的通道模式为PWM输出模式,并设置占空比。 5. 设置定时器互补输出使能和互补输出极性。 请注意,上述步骤仅提供了一个基本的配置示例,具体的配置参数和代码实现可能会根据你的具体需求和硬件环境而有所不同。建议参考GD32F303的官方手册和例程来获取更详细和准确的配置信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值