当前位置: 首页 > news >正文

HPMicro:PWM双更新

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

PWM双更新,就是在一个PWM周期内设置两个比较器来更新选定的比较器的值。如下图所示,在任意时刻修改CMP0影子寄存器以后,会在PWM计数器值到达CMP2和CMP3以后,CMP0的值才会生效。

以下是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);}#if 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的更新触发源*/#else/*CH8自己一个周期产生两个上升沿,独自触发两次*/cmp_config[3].mode = pwm_cmp_mode_output_compare;cmp_config[3].cmp = (reload >> 1) + 1;cmp_config[3].update_trigger = pwm_shadow_register_update_on_modify;cmp_config[4].mode = pwm_cmp_mode_output_compare;cmp_config[4].cmp = reload - 1;cmp_config[4].update_trigger = pwm_shadow_register_update_on_modify;pwm_output_channel_t pwm_output_ch_cfg;pwm_config_cmp(PWM, cmp_index + 2, &cmp_config[2]);pwm_config_cmp(PWM, cmp_index + 3, &cmp_config[3]);pwm_config_cmp(PWM, cmp_index + 4, &cmp_config[4]);/* 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 + 4;   /* end channel */pwm_output_ch_cfg.invert_output   = false;pwm_config_output_channel(PWM, 8, &pwm_output_ch_cfg);
#endif/*这里配置通道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 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("\n\n>> Generate edge aligned waveform and fault mode enable\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_fault_mode();//printf("\n\n>> Generate central 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_central_aligned_waveform();printf("\n\n>> Generate central aligned waveform in pair\n");printf("Two waveforms will be generated in pair, PWM P%d and P%d are target\n", PWM_OUTPUT_PIN1, PWM_OUTPUT_PIN2);printf("waveforms whose duty cycle will be updated from 0 - 100 and back to 0\n");generate_central_aligned_waveform_in_pair();//printf("\n\n>> Generate edge aligned jit 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_pwm_cmpjit_edge_aligned_waveform();disable_all_pwm_output();printf("test done\n");while(1);return 0;
}

测试波形如下所示:

 


http://www.mrgr.cn/news/49644.html

相关文章:

  • 智能EDA小白从0开始 —— DAY21 工作流程
  • [机械制造] 金属加工工艺:铁锤
  • C++ 匿名对象(没有名字的对象,类似于临时对象)
  • 计组_异常和中断
  • React中的useState和useEffect解析
  • QT QML 练习1
  • nginx使用手册<一>
  • Oracle漏洞修复 19.3 补丁包 升级为19.22
  • 噪声分布 双峰,模拟函数 或者模拟方法 python人工智能 深度神经网络
  • 大数据开发工程师的岗位技能要求及自我介绍参考(持续更新)
  • RTOS实时系统-信号量如何确保一次只有一个任务可以访问某个资源
  • 目标检测系统【环境详细配置过程】(CPU版本)
  • 架构师备考-背诵精华(架构开发方法)
  • 城域网——IP城域网、城域以太网、光城域网
  • 谈谈软件开发可行性研究的主要内容
  • Unity DOTS中的Archetype与Chunk
  • 【Redis】缓存预热、雪崩、击穿、穿透、过期删除策略、内存淘汰策略
  • 关于WPF(Windows Presentation Foundation)中Grid控件
  • [Linux网络编程]深入了解TCP通信API,看看底层做了啥(看了这篇文章,你也算是读了Linux源码的高手!)
  • 【开源物联网平台】Fastbee系统稳定性和压测报告