gpt4 book ai didi

Arduino Uno PWM - 奇怪的结果

转载 作者:行者123 更新时间:2023-12-02 00:01:03 27 4
gpt4 key购买 nike

我一直在 ATMega328P 上试验 PWM 波形生成模式。我得到了一些奇怪的结果,我无法确定是我编写固件的方式有问题还是我解释 datasheet 的方式有问题。 .

这是我为模拟 analogWrite() 函数编写的第一段代码:

// Waveform Generation Mode 0
// Table 15-4 of the datasheet

void setup()
{
DDRB = (1<<PB1); // set pin 9 as output

TCCR1A |= (1<<COM1A1);
OCR1A = 125;
}

void loop()
{
}

上面的代码从引脚 9 产生了大约 2.5V(49% 占空比)的平均电压输出。奇怪的是(对我来说)根据数据表,TIMER1 是一个 16 位定时器,所以它应该溢出在 65536 个刻度。据我了解,将 OCR1A 设置在 0 到 65535 之间会改变脉冲的占空比。因此,将 OCR1A 设置为 125 后,我不应该得到大约 0.01 V 而不是 2.5V 的输出吗?结果似乎暗示时钟在 255 处溢出。

第二次涉足 PWM 领域时,我想尝试使用 ATMega 的快速 PWM 模式创建 2.5V 信号。这是我得到的:

// Waveform Generation Mode 14
// Table 15-4 of the datasheet

void setup()
{
DDRB = (1<<PB1);

TCCR1A |= (1<<COM1A1) | (1<<WGM11);
TCCR1B |= (1<<WGM13) | (1<<WGM12) | (1<<CS10);

ICR1 = 19999;
OCR1A = 10000;
}

void loop()
{
}

我将 ICR1(溢出值)任意设置为 20000 个滴答,然后将 OCR1A(比较值)设置为其一半左右。我将 channel A 设置为非反相模式,但(我认为)如果我将其设置为反相模式,它不会有什么不同。当我将它闪存到 Arduino 上时,我从引脚 9 获得了 5V 的稳定平均电压(100% 占空比),但我终究无法弄清楚原因。

如果您能提供任何见解,我将不胜感激。

最佳答案

joeymorin 在 AVRfreaks 上的回答:

请注意,在 Uno 上,在 setup() 之前运行的 Arduino 初始化代码配置了很多东西,包括 328P 上的所有三个计时器。

来自wiring.c:

   sbi(TCCR0A, WGM01); 
sbi(TCCR0A, WGM00);
sbi(TCCR0B, CS01);
sbi(TCCR0B, CS00);
sbi(TIMSK0, TOIE0);

sbi(TCCR1B, CS11);
sbi(TCCR1B, CS10);
sbi(TCCR1A, WGM10);

sbi(TCCR2B, CS22);
sbi(TCCR2A, WGM20);

这将以 64 的预分频器启动所有三个定时器。

TIMER0 被置于模式 3(快速 PWM)并启用溢出中断以支持计时功能(millis()、micros() 和 delay())。

TIMER1 置于模式 1(固定 8 位相位校正 PWM)。

TIMER2 置于模式 1(相位校正 PWM)。

void setup() 
{
DDRB = (1<<PB1); // set pin 9 as output

TCCR1A |= (1<<COM1A1);
OCR1A = 125;
}

void loop()
{
}

由于 TCCR1A 中的 WGM10 已设置,设置 COM1A1 将在非反相模式下启用 PWM 输出,就像 analogWrite() 一样。

TIMER1 is a 16bit timer, so it should overflow at 65536 ticks. From what I understand setting OCR1A between 0 and 65535 will change the duty cycle of the pulse. So, having set the OCR1A at 125, shouldn't I be getting an output of around 0.01 V instead of 2.5V? The results seem to imply that the clock is overflowing at 255.

在模式 1 中,它的行为类似于 8 位定时器。

void setup() 
{
DDRB = (1<<PB1);

TCCR1A |= (1<<COM1A1) | (1<<WGM11);
TCCR1B |= (1<<WGM13) | (1<<WGM12) | (1<<CS10);

ICR1 = 19999;
OCR1A = 10000;
}

void loop()
{
}

由于 TCCR1A 中的 WGM10 已设置,设置 WGM11、WGM13 和 WGM12 将选择模式 15,而不是模式 14。模式 15 是快速 PWM,TOP = OCR1A(不是 ICR1)。由于您还使用 COM1A1 为 PWM 设置 OC1A 输出,这将导致 OC1A 保持高电平。

如前所述,如果您想在 Arduino 环境中配置定时器,您应该从头开始使用 = 而不是 |=。

theusch 写道:

And, for all I know, more might be run after setup()

来自 Arduino 的 main.cpp:代码:

#include <Arduino.h> 

int main(void)
{
init();

#if defined(USBCON)
USB.attach();
#endif

setup();

for (;;) {
loop();
if (serialEventRun) serialEventRun();
}

return 0;
}

张杰

关于Arduino Uno PWM - 奇怪的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21371678/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com