我正在做一个项目,我需要从两个不同的ADC和两个与它们相关的不同PWM信号进行两次测量。测量值存储在变量freq
和duty
中。正如名称所述,我希望一个PWM信号的频率根据freq
的值而变化,而另一个必须根据duty
改变其占空比。问题是第一个信号工作正常,但第二个信号没有。
我正在使用ATmega328p。我尝试使用常量值而不是变量duty
,但同样的事情发生了。输出引脚(OC0B
)始终设置为高电平,即5 V DC,而不是PWM信号。功能非常简单:
//Timer0 configuration
TCCR0A = 0b00100011;
TCCR0B = 0b00001001; //Fast PWM, no prescaler, non-inverted, out OC0B
OCR0B = duty;
我已经对TCCR0
寄存器的值进行了三次检查,但一切似乎都是正确的。可能导致这种行为的原因是什么?
答案 0 :(得分:0)
将我的评论扩展为完整答案。
在page 140 of the datasheet上有一个列出所有内容的表格 “波形发生模式”。您在问题集中显示的代码 定时器进入模式7:快速PWM,TOP = OCR0A。在这 模式,定时器从零计数到存储在OCR0A中的值,然后 回滚到零并重新开始。您可以使用此模式生成 OC0B上的PWM信号。然后,您就可以控制两个信号 周期(通过设置OCR0A寄存器)和脉冲宽度(通过OCR0B)。 如果您未能设置OCR0A,则默认为零,并且它将不起作用。
如果你对256个时钟周期感到满意并且不想要 要更改它,您可以将255写入OCR0A。或者,你 可以将定时器设置为模式3:快速PWM,TOP = 0xff。在 在此模式下,周期为256个周期,与值无关 存储在OCR0A中。
下面是一个简单的测试程序,演示了模式3的使用。 它产生一个PWM信号,脉冲宽度为64个CPU周期 期间是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 (;;) ;
}