简体   繁体   English

如何在没有毛刺的情况下在 AVR 中实现零占空比 PWM?

[英]How to achieve zero duty cycle PWM in AVR without glitches?

I'm trying to use hardware PWM on ATmega2560, using TC0 (an 8-bit timer), in Fast PWM mode.我正在尝试在 ATmega2560 上使用硬件 PWM,在快速 PWM 模式下使用 TC0(一个 8 位定时器)。 I need to dynamically adjust the duty cycle, and this includes zero duty cycle.我需要动态调整占空比,这包括零占空比。 However, this does not appear to be easy or even possible.然而,这似乎并不容易,甚至不可能。 Quoting the datasheet:引用数据表:

The extreme values for the OCR0A Register represents special cases when generating a PWM waveform output in the fast PWM mode. OCR0A 寄存器的极值代表在快速 PWM 模式下生成 PWM 波形输出时的特殊情况。 If the OCR0A is set equal to BOTTOM, the output will be a narrow spike for each MAX+1 timer clock cycle.如果 OCR0A 设置为等于 BOTTOM,则输出将为每个 MAX+1 定时器时钟周期的窄尖峰。 Setting the OCR0A equal to MAX will result in a constantly high or low output (depending on the polarity of the output set by the COM0A1:0 bits).将 OCR0A 设置为 MAX 将导致输出始终为高电平或低电平(取决于 COM0A1:0 位设置的输出极性)。

So, setting OCR0A to 0 (=BOTTOM) will not actually result in zero duty cycle, and my tests confirm this.因此,将 OCR0A 设置为 0(=BOTTOM)实际上不会导致占空比为零,我的测试证实了这一点。 Some other approach needs to be taken.需要采取一些其他方法。

First, I've taught about using the OCR0A=MAX special case as described in the quote above.首先,我已经教过如何使用上面引用中描述的 OCR0A=MAX 特殊情况。 Combined with temporarily switching to inverted mode, this will result in zero duty cycle.结合临时切换到反向模式,这将导致零占空比。 However, since the COM0A1:0 bits are not double buffered (and not synchronized with OCR0A), this may result in a glitch in the output, if the mode is switched while the output is high (it will be left high until the next overflow).然而,由于 COM0A1:0 位不是双缓冲的(并且不与 OCR0A 同步),如果在输出为高电平时切换模式(它将保持高电平直到下一次溢出),这可能会导致输出出现故障)。 It does not appear to matter what order the OCR0A change and the mode change is done, both may glitch. OCR0A 更改和模式更改的顺序似乎无关紧要,两者都可能出现故障。

I've also considered another solution, to turn off the PWM by setting COM0A1:0=0.我还考虑了另一种解决方案,通过设置 COM0A1:0=0 来关闭 PWM。 This will immediately set the output to the value in the PORT register, which would be zero.这将立即将输出设置为 PORT 寄存器中的值,该值将为零。 But there's still the problem of going back from zero output to a non-zero duty cycle.但是仍然存在从零输出返回到非零占空比的问题。 From what I read in the datasheet, setting COM0A1:0 to re-enable the PWM will immediately switch the output pin to the output of the PWM, which may be an incorrect value until the next compare match or timer overflow.从我在数据表中读到的内容来看,设置 COM0A1:0 以重新启用 PWM 会立即将输出引脚切换到 PWM 的输出,这可能是不正确的值,直到下一次比较匹配或定时器溢出。 Hence, a glitch.因此,一个小故障。

Inverting the PWM overall may be applicable, but then the problem just becomes achieving full duty cycle, with symmetric issues.整体反转 PWM 可能适用,但问题就变成了实现全占空比,具有对称问题。

Note that it is not possible to leave the PWM waveform generation enabled while forcing the output of the pin via PORT, as explained in the datasheet:请注意,在通过 PORT 强制引脚输出的同时,不能启用 PWM 波形生成,如数据表中所述:

The Compare Output mode (COM0x1:0) bits have two functions.比较输出模式 (COM0x1:0) 位有两个功能。 The Waveform Generator uses the COM0x1:0 bits for defining the Output Compare (OC0x) state at the next Compare Match.波形发生器使用 COM0x1:0 位来定义下一次比较匹配时的输出比较(OC0x)状态。 Also, the COM0x1:0 bits control the OC0x pin output source.此外,COM0x1:0 位控制 OC0x 引脚输出源。

There is no way to let the PWM run for a cycle or so and switch to it when it's ready - enabling PWM immediately forces the pin output.没有办法让 PWM 运行一个周期左右并在它准备好时切换到它 - 启用 PWM 会立即强制引脚输出。

UPDATE.更新。 The phase-correct (center-aligned) PWM mode does not have this issue, and in my case is acceptable.相位校正(中心对齐)PWM 模式没有这个问题,在我的情况下是可以接受的。 I have tried it and confirmed that it works for both zero and full duty cycle.我已经尝试过并确认它适用于零和全占空比。

I just came through the same issue, but needed to stick with a Fast PWM setting on a atmega2560. 我刚刚遇到了同样的问题,但需要在atmega2560上坚持使用快速PWM设置。

The solution I found was to temporarily put the output pin to normal port operation (ie set the COMnX1 and COMnX1 bits of the TCCRnA register to zero when a zero duty cycle is needed : 我发现的解决方案是暂时将输出引脚置于正常端口操作(即,当需要零占空比时,将TCCRnA寄存器的COMnX1和COMnX1位设置为零:

TCCR1A &= (0<<COM1A1) & (0<<COM1A1);

you have two options: 你有两个选择:

  1. if you use the fast pwm: you can use an inverted pwm. 如果你使用快速pwm:你可以使用倒置pwm。 all you need to do is set the OC Pins to inverse mode and invert your pwm compare values. 您需要做的就是将OC Pins设置为反向模式并反转您的pwm比较值。 however - you now have glitches with 100% duty cycle 但是 - 你现在有100%占空比的毛刺

  2. use the phase correct pwm. 使用相位正确的pwm。 draw back is that the maximum frequency is halved. 退回是最大频率减半。

在快速pwm模式下,占空比为:(OCRx + 1)/(TOP + 1)* 100%因此在非反相模式下永远不会达到0%,在反相模式下永远不会达到100%。

There is another option, simply change pin direction to input like this: 还有另一种选择,只需将引脚方向改为输入,如下所示:

DDRB &= ~(1<<PB1);

..when you want to achieve zero duty cycle. ..当你想实现零占空比时。 I'm aware this is some kind of a hack and sometimes it's not desired to perform such a thing, but anyway it works. 我知道这是某种黑客攻击,有时不希望执行这样的操作,但无论如何它都有效。

Strangely sometimes zero duty cycle outputs constantly HIGH (I used PWM in comination with power down mode, although I set zero duty cycle before going to sleep);奇怪的是,有时零占空比输出一直处于高电平(我将 PWM 与掉电模式结合使用,尽管我在睡觉前设置了零占空比); using the the solution by vince solved this for me.使用 vince 的解决方案为我解决了这个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM