为什么没有PWM信号出来?
问题描述:
我正在做一个项目,我需要两个不同ADC的两个测量值以及两个不同的PWM信号。测量值存储在变量freq
和duty
中。如名称所示,我想要一个PWM信号的频率根据freq
的值而变化,而另一个必须根据duty
更改其占空比。问题是第一个信号工作正常,但第二个信号没有。为什么没有PWM信号出来?
我正在使用ATmega328p。我试过使用一个常量值而不是变量duty
,但发生了同样的情况。代替PWM信号,输出引脚(OC0B
)始终设置为高电平,即5 V DC。该功能是非常简单的:
//Timer0 configuration
TCCR0A = 0b00100011;
TCCR0B = 0b00001001; //Fast PWM, no prescaler, non-inverted, out OC0B
OCR0B = duty;
我有三重检查TCCR0
寄存器的值,但一切似乎是正确的。什么可能导致这种行为?
答
将我的评论扩展为完整的答案。
在page 140 of the datasheet有一个表格列出所有 “波形生成模式”。您在问题中显示的代码将 计时器设置为模式 7:使用TOP的快速PWM = OCR0A。在这个 模式下,定时器从零计数到存储在OCR0A中的值,然后 回滚到零并重新开始。您可以使用此模式在OC0B上产生一个PWM信号 。然后,您可以同时控制信号 (通过设置OCR0A寄存器)和脉冲宽度(通过OCR0B)。 如果您未能设置OCR0A,它默认为零,并且不起作用。
如果您满意的时钟周期为256 并且不希望 更改它,您可以将 255写入OCR0A。或者,您可以将定时器设置为模式 3:使用TOP的快速PWM = 0xff。在 此模式下,周期为256 个周期,与存储在OCR0A中的值 无关。
下面是一个简单的测试程序,演示如何使用的模式 3. 它生成其中脉冲宽度为64个CPU周期的PWM信号和 周期是256个 周期。
#include <avr/io.h>
int main(void)
{
uint8_t duty = 64;
// Set pin PD5 = OC0B as output.
DDRD |= _BV(PD5);
// Configure Timer 0.
OCR0B = duty - 1; // set duty cycle
TCCR0A = _BV(COM0B1) // non-inverting PWM on OC0B
| _BV(WGM00) // mode 3: fast PWM, top = 0xff
| _BV(WGM01); // ditto
TCCR0B = _BV(CS00); // clock at F_CPU
for (;;) ;
}
有关于它的[这个网页]上的广泛讨论(http://www.avrfreaks.net/forum/solved-atmega328p-output-pwm-oc0a-and-oc0b)。 –
您可能想使用模式3而不是模式7.或者您忘记设置“OCR0A”。 –
@EdgarBonet对不起,我的无知,但你是什么意思?我不明白“模式3”或7是什么意思。另外,如果我想使用B输出,为什么要设置'OCR0A'? – Tendero