为什么PWM信号不出来?
Why isn't PWM signal coming out?
我正在做一个项目,我需要来自两个不同 ADC 的两个测量值和两个与之相关的不同 PWM 信号。测量值存储在变量 freq
和 duty
中。顾名思义,我希望一个 PWM 信号的频率根据 freq
的值而变化,而另一个必须根据 duty
改变其占空比。问题是第一个信号正常,但第二个信号不正常。
我正在使用 ATmega328p。我试过使用常量值而不是变量 duty
但同样的事情发生了。输出引脚 (OC0B
) 不是 PWM 信号,而是始终设置为高电平,即 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 上有一个 table 列出所有
“波形生成模式”。您在问题集中显示的代码
定时器进入模式 7:TOP = OCR0A 的快速 PWM。在这个
模式下,定时器从零开始计数到 OCR0A 中存储的值,然后
回滚到零并重新开始。您可以使用此模式生成
OC0B 上的 PWM 信号。然后你就可以控制这两个信号
周期(通过设置 OCR0A 寄存器)和脉冲宽度(通过 OCR0B)。
如果设置OCR0A失败,默认为0,无效
如果您对 256 个时钟周期感到满意并且不想
要更改它,您可以将 255 写入 OCR0A。或者,你
可以将定时器设置为模式 3:TOP = 0xff 的快速 PWM。在
此模式下,周期为 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 (;;) ;
}
我正在做一个项目,我需要来自两个不同 ADC 的两个测量值和两个与之相关的不同 PWM 信号。测量值存储在变量 freq
和 duty
中。顾名思义,我希望一个 PWM 信号的频率根据 freq
的值而变化,而另一个必须根据 duty
改变其占空比。问题是第一个信号正常,但第二个信号不正常。
我正在使用 ATmega328p。我试过使用常量值而不是变量 duty
但同样的事情发生了。输出引脚 (OC0B
) 不是 PWM 信号,而是始终设置为高电平,即 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 上有一个 table 列出所有 “波形生成模式”。您在问题集中显示的代码 定时器进入模式 7:TOP = OCR0A 的快速 PWM。在这个 模式下,定时器从零开始计数到 OCR0A 中存储的值,然后 回滚到零并重新开始。您可以使用此模式生成 OC0B 上的 PWM 信号。然后你就可以控制这两个信号 周期(通过设置 OCR0A 寄存器)和脉冲宽度(通过 OCR0B)。 如果设置OCR0A失败,默认为0,无效
如果您对 256 个时钟周期感到满意并且不想 要更改它,您可以将 255 写入 OCR0A。或者,你 可以将定时器设置为模式 3:TOP = 0xff 的快速 PWM。在 此模式下,周期为 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 (;;) ;
}