我正在做一个项目,我需要两个测量来自两个不同的ADC和两个不同的PWM信号与他们有关。测量的值存储在变量freq
和duty
中。由于名称状态,我希望一个脉宽调制信号的频率变化取决于freq
的值,而另一个必须改变其占空比取决于duty
。问题是,第一个信号工作正常,但第二个没有。
我用的是ATmega328p。我尝试使用一个常量值而不是变量duty
,但同样的情况发生了。输出引脚(OC0B
)不是脉宽调制信号,而是不断地被设定为高电压,即5V直流。这个功能非常简单:
//Timer0 configuration
TCCR0A = 0b00100011;
TCCR0B = 0b00001001; //Fast PWM, no prescaler, non-inverted, out OC0B
OCR0B = duty;
我已经三次检查了TCCR0
寄存器的值,但是一切似乎都是正确的。是什么导致了这种行为?
发布于 2017-10-13 00:49:35
把我的评论扩大到一个完整的答案。
在数据表第140页上有一个表,列出了所有的“波形生成模式”。您在问题中显示的代码将计时器设置为模式7:使用TOP = OCR0A快速脉宽调制。在这种模式下,计时器从零计数到存储在OCR0A中的值,然后回滚到零,然后重新启动。您可以使用此模式在OC0B上生成脉宽调制信号。然后,您将能够控制信号周期(通过设置OCR0A寄存器)和脉宽(通过OCR0B)。如果您未能设置OCR0A,则默认为零,并且它将无法工作。
如果您对256个时钟周期的周期感到满意,并且不想更改它,那么您可以在OCR0A中编写新的255个。或者,您可以将计时器设置为模式3:使用TOP = 0 0xff的快速脉宽调制。在这种模式下,无论存储在OCR0A中的值如何,周期都是256个循环。
下面是一个简单的测试程序,演示了模式3的使用。它产生一个脉宽为64个CPU周期,周期为256个周期的PWM信号。
#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 (;;) ;
}
https://stackoverflow.com/questions/46595376
复制