HPMicro:PWM双更新

PWM 定时器的比较器 CMPx,它们的影子寄存器值生效时刻可以通过MPCFGx[CMPSHDWUPT] 位设置:定时器的某一个 CMP 发生匹配后生效,用户可以通过 GCR [CMPSHDWSEL] 从比较器 0∼15 中选择一个,匹配可以是该比较器的输出比较,也可以是输入捕获。用户可以选择把选中的比较器 CMPx的值设为与 RLD xRLD 相等,达到一个完整的 PWM 周期后更新影子寄存器的目的。

PWM双更新,就是在一个PWM周期内设置两个比较器来更新选定的比较器的值。如下图所示,在任意时刻修改CMP0影子寄存器以后,会在PWM计数器值到达CMP2和CMP3以后,CMP0的值才会生效。PWM双更新的主要作用是可以及时更新CMP0,使PWM波形及时变化,不致于等到经过一个PWM周期才使更新生效。

以下是PWM V1版本实现PWM双更新功能的示例代码:

void pwm_cmp_change(void)
{
	static uint32_t timer = 0;
	timer++;

	if(timer % 2 == 0)
	{
			pwm_update_raw_cmp_edge_aligned(PWM, 0, reload * 2 / 3);
			pwm_update_raw_cmp_edge_aligned(PWM, 1, reload - 1);
	}
	else if(timer % 2 == 1)
	{
			pwm_update_raw_cmp_edge_aligned(PWM, 0, reload * 1 / 3);
			pwm_update_raw_cmp_edge_aligned(PWM, 1, reload - 1);
	}
}

void generate_central_aligned_waveform_in_pair(void)
{
    uint8_t cmp_index = 0;
    uint32_t duty, duty_step;
    bool increase_duty_cycle = true;
    pwm_cmp_config_t cmp_config[5] = {0};
    pwm_pair_config_t pwm_pair_config = {0};
	pwm_output_channel_t pwm_output_ch_cfg;

    pwm_stop_counter(PWM);
    reset_pwm_counter();

    /*
     * reload and start counter
     */
    pwm_set_reload(PWM, 0, reload);
    pwm_set_start_count(PWM, 0, 0);

    /*
     * config cmp1 and cmp2
     */
    cmp_config[0].mode = pwm_cmp_mode_output_compare;
    cmp_config[0].cmp = reload/4;
    cmp_config[0].update_trigger = pwm_shadow_register_update_on_hw_event; //pwm_shadow_register_update_on_modify  pwm_shadow_register_update_on_hw_event; //pwm_shadow_register_update_on_hw_event;

    cmp_config[1].mode = pwm_cmp_mode_output_compare;
    cmp_config[1].cmp = reload+1;
    cmp_config[1].update_trigger = pwm_shadow_register_update_on_sh_synci;

    cmp_config[2].mode = pwm_cmp_mode_output_compare;  // cmp2发生匹配,触发cpm0生效
    cmp_config[2].cmp = reload>>1;
    cmp_config[2].update_trigger = pwm_shadow_register_update_on_modify;

	cmp_config[3].mode = pwm_cmp_mode_output_compare;  // cmp3发生匹配,触发cpm0生效
    cmp_config[3].cmp = reload - 1;
    cmp_config[3].update_trigger = pwm_shadow_register_update_on_modify;

	cmp_config[4].mode = pwm_cmp_mode_output_compare;  // 触发产生SHRLDSYNCI上升沿
    cmp_config[4].cmp = (reload>>1) + 1000;
    cmp_config[4].update_trigger = pwm_shadow_register_update_on_modify;

    pwm_get_default_pwm_pair_config(PWM, &pwm_pair_config);
    pwm_pair_config.pwm[0].enable_output = true;
    pwm_pair_config.pwm[0].dead_zone_in_half_cycle = 8000;
    pwm_pair_config.pwm[0].invert_output = false;

    pwm_pair_config.pwm[1].enable_output = true;
    pwm_pair_config.pwm[1].dead_zone_in_half_cycle = 16000;
    pwm_pair_config.pwm[1].invert_output = false;

    /*
     * config pwm
     */
    if (status_success != pwm_setup_waveform_in_pair(PWM, PWM_OUTPUT_PIN1, &pwm_pair_config, cmp_index, cmp_config, 2)) {
        printf("failed to setup waveform\n");
        while(1);
    }

    /*CMP2,CMP3各触发一次*/
    pwm_config_cmp(PWM, cmp_index + 2, &cmp_config[2]);
    /* Set comparator channel to generate a trigger signal */
    pwm_output_ch_cfg.cmp_start_index = cmp_index + 2;   /* start channel */
    pwm_output_ch_cfg.cmp_end_index   = cmp_index + 2;   /* end channel */
    pwm_output_ch_cfg.invert_output   = false;
    pwm_load_cmp_shadow_on_match(PWM, cmp_index + 2,  &cmp_config[2]); /*将CMP2做为 CMP0的更新触发源*/

    pwm_config_cmp(PWM, cmp_index + 3, &cmp_config[3]);
    /* Set comparator channel to generate a trigger signal */
    pwm_output_ch_cfg.cmp_start_index = cmp_index + 3;   /* start channel */
    pwm_output_ch_cfg.cmp_end_index   = cmp_index + 3;   /* end channel */
    pwm_output_ch_cfg.invert_output   = false;
	pwm_load_cmp_shadow_on_match(PWM, cmp_index + 3,  &cmp_config[3]); /*将CMP3做为 CMP0的更新触发源*/


    /*这里配置通道10连接到互联管理器,用来触发用于输出PWM的比较器1更新*/
    pwm_output_ch_cfg.cmp_start_index = cmp_index + 4;   /* start channel */
    pwm_output_ch_cfg.cmp_end_index   = cmp_index + 4;   /* end channel */
    pwm_output_ch_cfg.invert_output   = false;
    pwm_config_output_channel(PWM, 10, &pwm_output_ch_cfg);
	pwm_config_cmp(PWM, cmp_index + 4, &cmp_config[4]);

    trgm_output_t trgm0_io_config0 = {0};
    trgm0_io_config0.invert = 0;
    trgm0_io_config0.type = trgm_output_same_as_input;
    trgm0_io_config0.input = HPM_TRGM0_INPUT_SRC_PWM0_CH10REF;
    trgm_output_config(HPM_TRGM0, HPM_TRGM0_OUTPUT_SRC_PWM0_SHRLDSYNCI, &trgm0_io_config0);

    pwm_start_counter(PWM);
    pwm_issue_shadow_register_lock_event(PWM);

	board_timer_create(50, pwm_cmp_change);  // 50ms修改一次比较器cmp0的影子寄存器值

	board_delay_ms(10000);
}

int main(void)
{
    uint32_t freq;
    board_init();
    init_pwm_pins(PWM);
    printf("pwm example\n");

    freq = clock_get_frequency(PWM_CLOCK_NAME);
    reload = freq / 1000 * PWM_PERIOD_IN_MS - 1;

    printf("\n\n>> Test force PWM output on P%d and P%d\n", PWM_OUTPUT_PIN1, PWM_OUTPUT_PIN2);
    test_pwm_force_output();

    printf("\n\n>> Generate central aligned waveform in pair\n");

    generate_central_aligned_waveform_in_pair();

    disable_all_pwm_output();
    printf("test done\n");
    while(1);
    return 0;
}

测试波形如下所示:

HPMicro:PWM双更新

版权声明:如无特殊标注,文章均来自网络,本站编辑整理,转载时请以链接形式注明文章出处,请自行分辨。

本文链接:https://www.shbk5.com/dnsj/74910.html