Arduino Uno PWM - 奇怪的结果

标签 arduino synthesizer pwm

我一直在 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/

相关文章:

linux - Arduino USB 与 Linux 的兼容性

node.js - 将外部 C++ 库与 Johnny Five 一起用于基于 Arduino 的项目

java - 尝试从麦克风获取数据时,每个样本都会输出平坦的零

linux - 如何正确配置 Beaglebone Black PWM

java - Arduino-处理 Serial.send/Serial.get 交互

Node.js 与 arduino 的 TCP 套接字

python - 第一次制作波表合成器......有人能给我指出正确的方向吗?

ruby - 我将如何以编程方式与 VST(i) 插件交互以合成音频?

c - STM32无法清除PWM中断标志

avr-gcc - ATtiny85 PWM 频率低于预期