2017-10-05 158 views
0

我正在做一个项目,我需要两个不同ADC的两个测量值以及两个不同的PWM信号。测量值存储在变量freqduty中。如名称所示,我想要一个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寄存器的值,但一切似乎是正确的。什么可能导致这种行为?

+0

有关于它的[这个网页]上的广泛讨论(http://www.avrfreaks.net/forum/solved-atmega328p-output-pwm-oc0a-and-oc0b)。 –

+0

您可能想使用模式3而不是模式7.或者您忘记设置“OCR0A”。 –

+0

@EdgarBonet对不起,我的无知,但你是什么意思?我不明白“模式3”或7是什么意思。另外,如果我想使用B输出,为什么要设置'OCR0A'? – Tendero

回答

0

将我的评论扩展为完整的答案。

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 (;;) ; 
}