PB7 上的 Atmega2560 PWM
Atmega2560 PWM on PB7
我试图在 Atmega2560 上使用定时器 0 从 PB7 引脚获取 PWM 输出,但没有成功。它应该为连接的 repro.My 产生音调 PWM 设置为:
DDRB = 0b11100000;
PORTB = 0b00000000;
OCR0A = 0x04;
TCCR0A = (0 << COM0A1) | (1 << COM0A0) | (1 << WGM01) | (0 << WGM00);
TCCR0B = (0 << WGM02) | (0 << CS02) | (0 << CS01) | (0 << CS00);
然后我有这个函数,它应该产生声音:
void SoundOutput(unsigned int uintTone)
{
if (uintTone != 0)
{
LED_2(1);
OCR0A = uintTone;
TCCR0B |= (1 << CS02) | (1 << CS01) | (1 << CS00);
}
else
{
TCCR0B &= ~((1 << CS02) | (1 << CS01) | (1 << CS00));
}
}
但是当我用音调参数调用它时没有任何反应。你能帮我么?
根据您的评论,您正在使用 ~12MHz 时钟作为定时器的输入,并且根据您的代码,您在 CTC 模式下使用 8 位定时器 0,OCR0A 作为您的顶部。您已将 OC0A 设置为打开比较匹配。
根据 2560 数据表,定时器的频率由下式给出:
F_CLK/(2*(1 + OCR0A)) | F_CLK~=12MHz
这是一个 8 位定时器,这意味着您的 PWM 可以产生的最小频率由下式给出:
12e6/(2*(1 + 255)) ~= 20KHz
除非您减慢用于计时器的时钟或使用计数更高的计时器,否则您根本无法使用该配置生成可听见的音调。
1) 使用 16 位计数器(即 timer1)。这将为您提供约 90Hz 的最小频率和约 6MHz 的最大频率,这应该为您提供足够的范围来生成音调:
/* WGM BITS = 0100: CTC Mode */
/* COMA BITS = 01: Toggle OC1A on compare match */
/* CS BITS = 111: External clock source on rising edge */
TCCR1A = (0 << COM1A1) | (1 << COM1A0) | (0 << WGM01) | (0 << WGM00);
TCCR1B = (1 << WGM12) | (1 << WGM13) | (1 << CS02) | (1 << CS01) | (1 << CS00);
2) 使用内部时钟源作为定时器时钟,而不是外部时钟源。除非你改变了保险丝位或者你在代码中的某个地方改变它,否则时钟将为 1MHz。将时钟按 8 进行预分频可为您提供 ~250Hz - ~60KHz 的频率范围。
/* WGM BITS = 010: CTC Mode */
/* COMA BITS = 01: Toggle OC1A on compare match */
/* CS BITS = 010: Prescale the internal clock by 8 */
TCCR0A = (0 << COM0A1) | (1 << COM0A0) | (1 << WGM01) | (0 << WGM00);
TCCR0B = (0 << WGM02) | (0 << CS02) | (1 << CS01) | (0 << CS00);
我试图在 Atmega2560 上使用定时器 0 从 PB7 引脚获取 PWM 输出,但没有成功。它应该为连接的 repro.My 产生音调 PWM 设置为:
DDRB = 0b11100000;
PORTB = 0b00000000;
OCR0A = 0x04;
TCCR0A = (0 << COM0A1) | (1 << COM0A0) | (1 << WGM01) | (0 << WGM00);
TCCR0B = (0 << WGM02) | (0 << CS02) | (0 << CS01) | (0 << CS00);
然后我有这个函数,它应该产生声音:
void SoundOutput(unsigned int uintTone)
{
if (uintTone != 0)
{
LED_2(1);
OCR0A = uintTone;
TCCR0B |= (1 << CS02) | (1 << CS01) | (1 << CS00);
}
else
{
TCCR0B &= ~((1 << CS02) | (1 << CS01) | (1 << CS00));
}
}
但是当我用音调参数调用它时没有任何反应。你能帮我么?
根据您的评论,您正在使用 ~12MHz 时钟作为定时器的输入,并且根据您的代码,您在 CTC 模式下使用 8 位定时器 0,OCR0A 作为您的顶部。您已将 OC0A 设置为打开比较匹配。
根据 2560 数据表,定时器的频率由下式给出:
F_CLK/(2*(1 + OCR0A)) | F_CLK~=12MHz
这是一个 8 位定时器,这意味着您的 PWM 可以产生的最小频率由下式给出:
12e6/(2*(1 + 255)) ~= 20KHz
除非您减慢用于计时器的时钟或使用计数更高的计时器,否则您根本无法使用该配置生成可听见的音调。
1) 使用 16 位计数器(即 timer1)。这将为您提供约 90Hz 的最小频率和约 6MHz 的最大频率,这应该为您提供足够的范围来生成音调:
/* WGM BITS = 0100: CTC Mode */
/* COMA BITS = 01: Toggle OC1A on compare match */
/* CS BITS = 111: External clock source on rising edge */
TCCR1A = (0 << COM1A1) | (1 << COM1A0) | (0 << WGM01) | (0 << WGM00);
TCCR1B = (1 << WGM12) | (1 << WGM13) | (1 << CS02) | (1 << CS01) | (1 << CS00);
2) 使用内部时钟源作为定时器时钟,而不是外部时钟源。除非你改变了保险丝位或者你在代码中的某个地方改变它,否则时钟将为 1MHz。将时钟按 8 进行预分频可为您提供 ~250Hz - ~60KHz 的频率范围。
/* WGM BITS = 010: CTC Mode */
/* COMA BITS = 01: Toggle OC1A on compare match */
/* CS BITS = 010: Prescale the internal clock by 8 */
TCCR0A = (0 << COM0A1) | (1 << COM0A0) | (1 << WGM01) | (0 << WGM00);
TCCR0B = (0 << WGM02) | (0 << CS02) | (1 << CS01) | (0 << CS00);