在FOC控制中,一般采用下桥臂采样,而在下桥臂采样的方式中常常采用在下桥臂全部导通时进行采样和进行FOC控制。
下面是七段式SVPWM输出时的PWM波形
在七段式SVPWM控制时可见在两边(非中间)的0矢量时正是下桥臂都导通的时刻,也就是最适合来触发ADC采样的时刻。
也就是如下情况
为了符合我们的控制,FOC控制中PWM的配置常常采用中央对齐方式1+PWM模式B,互为互补电平的两个引脚的有效电平都设为高电平有效的方式
中央对齐方式1:每一个PWM周期都要通过ADC采样一次相电流。当RCR设置1时 ,ARR寄存器的值倒数到0时会触发一次Update Event
PWM模式B:在计数值大于比较值时输出有效电平
static uint32_t timer1_period = 0;
static uint8_t motor_state = MOTOR_CLOSE;
void drv_pwm_init(void)
{
gpio_init_type gpio_init_struct;
tmr_output_config_type tmr_output_struct;
crm_clocks_freq_type crm_clocks_freq_struct;
tmr_brkdt_config_type tmr_brkdt_config_struct;
/* enable tmr1/gpioa/gpiob clock */
crm_periph_clock_enable(CRM_TMR1_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
gpio_default_para_init(&gpio_init_struct);
/* timer1 output pin Configuration */
gpio_init_struct.gpio_pins = GPIO_PINS_8 | GPIO_PINS_9 | GPIO_PINS_10;
gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_init(GPIOA, &gpio_init_struct);
gpio_default_para_init(&gpio_init_struct);
gpio_init_struct.gpio_pins = GPIO_PINS_13 | GPIO_PINS_14 | GPIO_PINS_15;
gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_init(GPIOB, &gpio_init_struct);
tmr_clock_source_div_set(TMR1, TMR_CLOCK_DIV1);
/* get system clock */
crm_clocks_freq_get(&crm_clocks_freq_struct);
timer1_period = (crm_clocks_freq_struct.sclk_freq / (PWM_FREQ * 2));
tmr_base_init(TMR1, timer1_period - 1, 0);
tmr_cnt_dir_set(TMR1, TMR_COUNT_TWO_WAY_1); /* 每一个PWM周期都要通过ADC采样一次相电流。当RCR设置1时ARR寄存器的值倒数到0时会触发一次Update Event */
tmr_period_buffer_enable(TMR1, TRUE);
tmr_output_default_para_init(&tmr_output_struct);
tmr_output_struct.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_B; /* 在计数值大于比较值时输出有效电频 */
tmr_output_struct.oc_output_state = TRUE;
tmr_output_struct.oc_polarity = TMR_OUTPUT_ACTIVE_HIGH;
tmr_output_struct.oc_idle_state = FALSE;
tmr_output_struct.occ_output_state = TRUE;
tmr_output_struct.occ_polarity = TMR_OUTPUT_ACTIVE_HIGH;
tmr_output_struct.occ_idle_state = FALSE;
/* channel 1 */
tmr_output_channel_config(TMR1, TMR_SELECT_CHANNEL_1, &tmr_output_struct);
tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_1, 0);
/* channel 2 */
tmr_output_channel_config(TMR1, TMR_SELECT_CHANNEL_2, &tmr_output_struct);
tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_2, 0);
/* channel 3 */
tmr_output_channel_config(TMR1, TMR_SELECT_CHANNEL_3, &tmr_output_struct);
tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_3, 0);
/* channel 4 */
tmr_output_channel_config(TMR1, TMR_SELECT_CHANNEL_4, &tmr_output_struct);
tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_4, 1); /* 用于触发ADC的定时器通道比较值设为1 */
tmr_brkdt_default_para_init(&tmr_brkdt_config_struct);
tmr_brkdt_config_struct.brk_enable = FALSE;
tmr_brkdt_config_struct.auto_output_enable = FALSE;
tmr_brkdt_config_struct.deadtime = 196;
tmr_brkdt_config_struct.fcsodis_state = FALSE;
tmr_brkdt_config_struct.fcsoen_state = FALSE;
tmr_brkdt_config_struct.brk_polarity = TMR_BRK_INPUT_ACTIVE_HIGH;
tmr_brkdt_config_struct.wp_level = TMR_WP_OFF;
tmr_brkdt_config(TMR1, &tmr_brkdt_config_struct);
/* output enable */
tmr_output_enable(TMR1, TRUE);
/* enable tmr1 */
tmr_counter_enable(TMR1, TRUE);
motor_state = MOTOR_OPEN;
close_motor();
}
uint32_t get_pwm_frequence(void)
{
return PWM_FREQ;
}
uint32_t get_pwm_period(void)
{
return timer1_period;
}
void pwm_out_set(uint32_t tim1_channel1_ccr, uint32_t tim1_channel2_ccr,uint32_t tim1_channel3_ccr)
{
tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_1, tim1_channel1_ccr);
tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_2, tim1_channel2_ccr);
tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_3, tim1_channel3_ccr);
}
void open_motor(void)
{
if (motor_state == MOTOR_CLOSE) {
tmr_channel_enable(TMR1, TMR_SELECT_CHANNEL_1, TRUE);
tmr_channel_enable(TMR1, TMR_SELECT_CHANNEL_2, TRUE);
tmr_channel_enable(TMR1, TMR_SELECT_CHANNEL_3, TRUE);
tmr_channel_enable(TMR1, TMR_SELECT_CHANNEL_1C, TRUE);
tmr_channel_enable(TMR1, TMR_SELECT_CHANNEL_2C, TRUE);
tmr_channel_enable(TMR1, TMR_SELECT_CHANNEL_3C, TRUE);
motor_state = MOTOR_OPEN;
}
}
void close_motor(void)
{
if (motor_state == MOTOR_OPEN) {
tmr_channel_enable(TMR1, TMR_SELECT_CHANNEL_1, FALSE);
tmr_channel_enable(TMR1, TMR_SELECT_CHANNEL_2, FALSE);
tmr_channel_enable(TMR1, TMR_SELECT_CHANNEL_3, FALSE);
tmr_channel_enable(TMR1, TMR_SELECT_CHANNEL_1C, FALSE);
tmr_channel_enable(TMR1, TMR_SELECT_CHANNEL_2C, FALSE);
tmr_channel_enable(TMR1, TMR_SELECT_CHANNEL_3C, FALSE);
motor_state = MOTOR_CLOSE;
}
}
uint8_t get_motor_state(void)
{
return motor_state;
}