GD32F303应用笔记(四) Timer&SPWM
目录
1. 简介
2. SPWM原理与实现流程
- SPWM(正弦脉宽调制):通过调节PWM占空比,使输出波形逼近正弦波。
- 实现步骤:
- 预先生成正弦查找表(查表法,效率高)。
- 配置TIMER1定时器,定时中断推进SPWM角度。
- 查表获取三相PWM占空比,分别输出到三相PWM通道。
- 通过调整推进步进实现转速控制。
3. 关键参数与查表
#define SIN_TABLE_SIZE 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));
}
}
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_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);
timer_initpara.prescaler = 0;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 6000 - 1;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER0,&timer_initpara);
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);
uint16_t duty = 0;
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);
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);
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);
timer_primary_output_config(PWM_PHASE_A_TIMER,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;
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输出
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.结束
波形图
