先楫推出的HPM6E00系列芯片,PWM功能升级到了V2版本。和V1版本不同的是,V2版本的每组PWM模块包含4个独立的PWM生成模块,每个PWM生成模块包含一个counter和4个比较器,可以生成4组频率不同的PWM波。每个PWM生成模块,对应生成两个PWM输出通道。不同于PWM V1的将多个比较器分配到一个PWM输出通道的方式。PWM V2的一个PWM生成模块,4个比较器通过设置比较器的值来控制2个PWM通道的值,可以单独控制,也可以成对控制。
PWM V2同样支持故障保护功能,通过输入IO来停止PWM的发波。最多支持16个IO,直接作为故障信号的触发源,这个mux在PWM内部。
下面通过PWM V2的例程,讲解PWM V2控制单通道PWM的原理。
以生成PWM 通道1为例:通过影子寄存器0来设置PWM周期,比较器0和比较器1控制PWM channel 0,比较器2和比较器3控制PWM channel 1。比较器2的值来自影子寄存器3,比较器3的值来自影子寄存器4。当PWM开始计数时,计数值达到比较器2和比较器3的值的时候,进行电平翻转。达到counter的值时重新进行计数,不会进行电平翻转。例程中,比较器3的值固定为reload,通过改变比较器2的值来改变占空比。
void generate_edge_aligned_waveform(void)
{
uint32_t duty, duty_step;
bool increase_duty_cycle = true;
pwmv2_disable_counter(PWM, pwm_counter_0);
pwmv2_reset_counter(PWM, pwm_counter_0);
pwmv2_shadow_register_unlock(PWM);
pwmv2_set_shadow_val(PWM, PWMV2_SHADOW_INDEX(0), reload, 0, false);
pwmv2_set_shadow_val(PWM, PWMV2_SHADOW_INDEX(1), reload + 1, 0, false);
pwmv2_set_shadow_val(PWM, PWMV2_SHADOW_INDEX(2), reload, 0, false);
pwmv2_set_shadow_val(PWM, PWMV2_SHADOW_INDEX(3), reload >> 1, 0, false);
pwmv2_set_shadow_val(PWM, PWMV2_SHADOW_INDEX(4), reload, 0, false);
pwmv2_counter_select_data_offset_from_shadow_value(PWM, pwm_counter_0, PWMV2_SHADOW_INDEX(0));
pwmv2_counter_burst_disable(PWM, pwm_counter_0);
pwmv2_set_reload_update_time(PWM, pwm_counter_0, pwm_reload_update_on_reload);
pwmv2_select_cmp_source(PWM, PWMV2_CMP_INDEX(0), cmp_value_from_shadow_val, PWMV2_SHADOW_INDEX(1));
pwmv2_select_cmp_source(PWM, PWMV2_CMP_INDEX(1), cmp_value_from_shadow_val, PWMV2_SHADOW_INDEX(2));
pwmv2_select_cmp_source(PWM, PWMV2_CMP_INDEX(2), cmp_value_from_shadow_val, PWMV2_SHADOW_INDEX(3));
pwmv2_select_cmp_source(PWM, PWMV2_CMP_INDEX(3), cmp_value_from_shadow_val, PWMV2_SHADOW_INDEX(4));
pwmv2_shadow_register_lock(PWM);
//pwmv2_disable_four_cmp(PWM, BOARD_APP_PWM_OUT1);
pwmv2_disable_four_cmp(PWM, BOARD_APP_PWM_OUT2);
//pwmv2_channel_enable_output(PWM, BOARD_APP_PWM_OUT1);
pwmv2_channel_enable_output(PWM, BOARD_APP_PWM_OUT2);
pwmv2_enable_counter(PWM, pwm_counter_0);
pwmv2_start_pwm_output(PWM, pwm_counter_0);
//pwmv2_shadow_register_unlock(PWM);
//pwmv2_set_shadow_val(PWM, PWMV2_SHADOW_INDEX(1), 0, 0, false);
//pwmv2_shadow_register_lock(PWM);
//pwmv2_shadow_register_unlock(PWM);
//pwmv2_set_shadow_val(PWM, PWMV2_SHADOW_INDEX(4), 0, 0, false);
//pwmv2_shadow_register_lock(PWM);
//board_delay_ms(1000);
// 占空比100%,PWM默认低电平,CMP2先翻转
pwmv2_shadow_register_unlock(PWM);
pwmv2_set_shadow_val(PWM, PWMV2_SHADOW_INDEX(3), 2, 0, false);
pwmv2_shadow_register_lock(PWM);
board_delay_ms(1000);
// 占空比50%
pwmv2_shadow_register_unlock(PWM);
pwmv2_set_shadow_val(PWM, PWMV2_SHADOW_INDEX(3), reload/2, 0, false);
pwmv2_shadow_register_lock(PWM);
board_delay_ms(1000);
// 占空比75%
pwmv2_shadow_register_unlock(PWM);
pwmv2_set_shadow_val(PWM, PWMV2_SHADOW_INDEX(3), reload/4, 0, false);
pwmv2_shadow_register_lock(PWM);
board_delay_ms(1000);
pwmv2_disable_counter(PWM, pwm_counter_0);
pwmv2_reset_counter(PWM, pwm_counter_0);
pwmv2_shadow_register_unlock(PWM);
}
PWM故障保护:
void pwm_fault_async(void)
{
pwmv2_async_fault_source_config_t fault_cfg;
fault_cfg.async_signal_from_pad_index = BOARD_APP_PWM_FAULT_PIN;
fault_cfg.fault_async_pad_level = pad_fault_active_high;
pwmv2_config_async_fault_source(PWM, BOARD_APP_PWM_OUT1, &fault_cfg);
pwmv2_config_async_fault_source(PWM, BOARD_APP_PWM_OUT2, &fault_cfg);
pwmv2_set_fault_mode(PWM, BOARD_APP_PWM_OUT1, pwm_fault_output_0);
pwmv2_set_fault_mode(PWM, BOARD_APP_PWM_OUT2, pwm_fault_output_0);
pwmv2_enable_fault_from_pad(PWM, BOARD_APP_PWM_OUT1);
pwmv2_enable_fault_from_pad(PWM, BOARD_APP_PWM_OUT2);
}
int main(void)
{
uint32_t freq;
board_init();
init_pwm_pins(PWM);
init_pwm_fault_pins();
printf("pwm example\n");
freq = clock_get_frequency(PWM_CLOCK_NAME);
reload = freq / 10000 * PWM_PERIOD_IN_MS - 1;
pwm_fault_async();
printf("\n\n>> Test force PWM output on P%d and P%d\n", PWM_OUTPUT_PIN1, PWM_OUTPUT_PIN2);
pwm_force_output();
printf("\n\n>> Generate edge aligned waveform\n");
printf("Two waveforms will be generated, PWM P%d is the target waveform\n", PWM_OUTPUT_PIN1);
printf("whose duty cycle will be updated from 0 - 100 and back to 0; PWM P%d is a reference\n", PWM_OUTPUT_PIN2);
generate_edge_aligned_waveform();
printf("test done\n");
while (1) {
;
}
return 0;
}
程序测试结果:测试占空比
故障保护功能:给故障管脚输入高电平,PWM发波立即停止。