GD32F303应用笔记(四) Timer&SPWM

目录


1. 简介

  • 平台:GD32F303CCT6
  • 目标:使用TIMER1定时器周期性推进,查表输出三相SPWM波形,实现三相PWM驱动。
  • 相关宏定义可参考上一篇文章:GD32F303应用笔记(三) PWM

2. SPWM原理与实现流程

  • SPWM(正弦脉宽调制):通过调节PWM占空比,使输出波形逼近正弦波。
  • 实现步骤
    1. 预先生成正弦查找表(查表法,效率高)。
    2. 配置TIMER1定时器,定时中断推进SPWM角度。
    3. 查表获取三相PWM占空比,分别输出到三相PWM通道。
    4. 通过调整推进步进实现转速控制。

3. 关键参数与查表

#define SIN_TABLE_SIZE 360    // 正弦表大小(360度)

正弦表生成

uint16_t sin_table[SIN_TABLE_SIZE];

static void SinTableInit(void)
{
    for(int i = 0; i < SIN_TABLE_SIZE; i++) {
        float rad = i * 3.14159f / 180.0f;
        float sin_val = (sinf(rad) + 1.0f) * 0.5f;
        sin_table[i] = (uint16_t)(sin_val * (PWM_RESOLUTION - 1));
    }
}
  • 三相相位:A相0°,B相120°,C相240°

4. 定时器与PWM配置

TIMER0初始化

  • 具体宏定义可参考上一篇文章
void pwm_init(void)
{
    timer_oc_parameter_struct timer_ocintpara;
    timer_parameter_struct timer_initpara;
    timer_break_parameter_struct timer_breakpara;
    rcu_periph_clock_enable(RCU_TIMER0);  
    /* GPIO:推挽复用输出 50 MHz */
    gpio_init(PWM_PHASE_A_PORT, PWM_PHASE_A_FUNC, GPIO_OSPEED_50MHZ, PWM_PHASE_A_PIN);
    gpio_init(PWM_PHASE_B_PORT, PWM_PHASE_B_FUNC, GPIO_OSPEED_50MHZ, PWM_PHASE_B_PIN);
    gpio_init(PWM_PHASE_C_PORT, PWM_PHASE_C_FUNC, GPIO_OSPEED_50MHZ, PWM_PHASE_C_PIN);

    timer_deinit(TIMER0);

    timer_struct_para_init(&timer_initpara);
    /* TIMER0 configuration */

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

    /* CH0,CH1 and CH2 configuration in PWM mode */
    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_auto_reload_shadow_enable(TIMER0);
    
    /* 初始占空比 50% */
    uint16_t duty =  0; //PWM_OUT_HALF;  /* 50%占空比 */

    /* ---------- Configure PWM Channel 0 (Phase A) ---------- */
    /* CH2 → PA10 (PWMA) - Configure timer channel output */
    timer_channel_output_config(PWM_PHASE_A_TIMER, PWM_PHASE_A_TIMER_CH, &timer_ocintpara);
    timer_channel_output_pulse_value_config(PWM_PHASE_A_TIMER, PWM_PHASE_A_TIMER_CH, duty);
    timer_channel_output_mode_config(PWM_PHASE_A_TIMER, PWM_PHASE_A_TIMER_CH, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(PWM_PHASE_A_TIMER, PWM_PHASE_A_TIMER_CH,TIMER_OC_SHADOW_DISABLE);

    /* ---------- Configure PWM Channel 1 (Phase B) ---------- */
    /* CH1 → PA9 (PWMB) - Configure timer channel output */
    timer_channel_output_config(PWM_PHASE_B_TIMER, PWM_PHASE_B_TIMER_CH, &timer_ocintpara);
    timer_channel_output_pulse_value_config(PWM_PHASE_B_TIMER, PWM_PHASE_B_TIMER_CH, duty);
    timer_channel_output_mode_config(PWM_PHASE_B_TIMER, PWM_PHASE_B_TIMER_CH, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(PWM_PHASE_B_TIMER, PWM_PHASE_B_TIMER_CH,TIMER_OC_SHADOW_DISABLE);

    /* ---------- Configure PWM Channel 2 (Phase C) ---------- */
    /* CH0 → PA8 (PWMC) - Configure timer channel output */
    timer_channel_output_config(PWM_PHASE_C_TIMER, PWM_PHASE_C_TIMER_CH, &timer_ocintpara);
    timer_channel_output_pulse_value_config(PWM_PHASE_C_TIMER, PWM_PHASE_C_TIMER_CH, duty);
    timer_channel_output_mode_config(PWM_PHASE_C_TIMER, PWM_PHASE_C_TIMER_CH, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(PWM_PHASE_C_TIMER, PWM_PHASE_C_TIMER_CH,TIMER_OC_SHADOW_DISABLE);

    timer_breakpara.runoffstate      = TIMER_ROS_STATE_DISABLE;
    timer_breakpara.ideloffstate     = TIMER_IOS_STATE_DISABLE; 
    timer_breakpara.deadtime         = 200;
    timer_breakpara.breakpolarity    = TIMER_BREAK_POLARITY_LOW;
    timer_breakpara.outputautostate  = TIMER_OUTAUTO_ENABLE;
    timer_breakpara.protectmode      = TIMER_CCHP_PROT_OFF;
    timer_breakpara.breakstate       = TIMER_BREAK_DISABLE;
    timer_break_config(TIMER0, &timer_breakpara);

    /* TIMER0 primary output function enable */
    timer_primary_output_config(PWM_PHASE_A_TIMER,ENABLE);

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

TIMER1初始化

void Timer1Init(void){
    timer_parameter_struct t;
    rcu_periph_clock_enable(RCU_TIMER1);
    SinTableInit();
    t.prescaler = 120 - 1;        // 预分频
    t.period = 100 - 1;           // 周期 = 100us
    t.clockdivision = TIMER_CKDIV_DIV1;
    t.counterdirection = TIMER_COUNTER_UP;

    timer_init(TIMER1, &t);   
    timer_interrupt_enable(TIMER1, TIMER_INT_UP);
    timer_enable(TIMER1);
    nvic_irq_enable(TIMER1_IRQn, 3, 2);
}

5. SPWM输出与中断推进

三相SPWM输出

/* - **三相相位**:A相0°,B相120°,C相240° */
static void SpwmUpdatePhase(uint16_t angle_deg)
{
    uint16_t a = sin_table[angle_deg % SIN_TABLE_SIZE];
    uint16_t b = sin_table[(angle_deg + 120) % SIN_TABLE_SIZE];
    uint16_t c = sin_table[(angle_deg + 240) % SIN_TABLE_SIZE];

    timer_channel_output_pulse_value_config(PWM_PHASE_A_TIMER, PWM_PHASE_A_TIMER_CH, a);
    timer_channel_output_pulse_value_config(PWM_PHASE_B_TIMER, PWM_PHASE_B_TIMER_CH, b);
    timer_channel_output_pulse_value_config(PWM_PHASE_C_TIMER, PWM_PHASE_C_TIMER_CH, c);
}

SPWM推进任务

void SPWM_Task(void)
{
    static uint16_t current_spwm_index = 0;

    // 角度推进
    if (1)    // 这里可增加条件用于实现转动方向
        current_spwm_index = (current_spwm_index + 1) % 360;
    else
        current_spwm_index = (current_spwm_index - 1 + 360) % 360;

    SpwmUpdatePhase(current_spwm_index);
}

TIMER1中断服务

void TIMER1_IRQHandler(void)
{
    if(timer_interrupt_flag_get(TIMER1, TIMER_INT_UP) != RESET)
    {
        SPWM_Task();
        timer_interrupt_flag_clear(TIMER1, TIMER_INT_UP);
    }
}

6. 总结

  • 通过TIMER1定时器中断推进SPWM角度,查表输出三相PWM,实现高效的SPWM波形。
  • 适用于三相电机驱动、逆变等场合。
  • 关键点:查表法、定时器中断、三相相位、PWM输出配置。

7.结束

波形图

  • 蓝色为A相波形图
  • 红色为A相电流波形图

波形图