ESP32输出互补PWM波形中断

问题描述

在使用 ESP32 的 MCPWM 输出互补 PWM 时,发现在改变 PWM 频率时偶尔会出现波形中断的现象如下图所示。每次出现中断的前后频率都发生了改变,但不是每次频率改变都会触发这种中断的现象,中断前后的死区也是正常的。

放大中断区域进行测量,中断的时间如下图所示。可以看到是个很熟悉的数字,65.53568 ms,让人一下就联想到 16 位定时器计满就是 65535,第一感觉就是定时器溢出了,并且每次都是在频率改变的时候溢出。
个人猜想是在生成 PWM 的过程中,一个周期还没结束,新的值就被载入了,由于频率增加,计数值就会减小,如果当前的计数值已经比新的值大了,那么这个值就只能一直增加到溢出并重新计数到新的载入值才会生效。
举个例子,上一次载入的计数值是 1k,现在要增加频率为两倍,计数值就要减小到 500,但是定时器现在已经数到了 800,只能继续向上计数,直到数到 65535 溢出后重新数到 500 才能生效。

网上查找了一下类似情况,果然是定时器的问题,具体的问题和自动预装载还有影子寄存器有关,文章作者使用的是 STM8 单片机,我找了一下 ESP32 的相关文档,发现 ESP32 关于影子寄存器的相关描述如下。

影子寄存器作为要写入有效寄存器的值的临时缓存。在用户配置的某个时间点,影子寄存器中的值被写入有效寄存器。在此之前,影子寄存器的内容对受控硬件没有任何直接影响。这有助于防止寄存器由软件异步修改时可能发生的错误硬件操作。影子寄存器和有效寄存器具有相同的存储器地址。软件总是写入或读取影子寄存器。有效寄存器的更新时间点由其特定的更新方式寄存器决定。更新时间点可以是 PWM 定时器等于零时,PWM 定时器等于周期时,同步时间点或立即。软件可以触发强制全局更新,根据影子寄存器更新模块中的所有有效寄存器。

更多相关信息可以去 ESP32技术参考手册 查看,在这就不多分析了。

解决方法

最简单的解决方法就是向上计数改为向下计数,这样的话,不管完没完成上个周期的计数都没影响。修改后 PWM 恢复正常。

参考资料