Answered by joeymorin on AVRfreaks:
Note that on the Uno, the Arduino init code that runs before your setup() configures a lot of stuff, including all three timers on the 328P.
From 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);
This starts all three timers with a prescaler of 64.
TIMER0 is placed into mode 3 (fast PWM) with the overflow interrupt enabled to support the timing functions (millis(), micros(), and delay()).
TIMER1 is placed into mode 1 (fixed 8-bit phase-correct PWM).
TIMER2 is placed into mode 1 (phase-correct PWM).
void setup()
{
DDRB = (1<<PB1); // set pin 9 as output
TCCR1A |= (1<<COM1A1);
OCR1A = 125;
}
void loop()
{
}
Since WGM10 in TCCR1A is already set, setting COM1A1 will enable the PWM output in non-inverting mode, just as analogWrite() would.
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.
In mode 1 it behaves like an 8-bit timer.
void setup()
{
DDRB = (1<<PB1);
TCCR1A |= (1<<COM1A1) | (1<<WGM11);
TCCR1B |= (1<<WGM13) | (1<<WGM12) | (1<<CS10);
ICR1 = 19999;
OCR1A = 10000;
}
void loop()
{
}
Since WGM10 in TCCR1A is already set, setting WGM11, WGM13, and WGM12 will select mode 15, not mode 14. Mode 15 is fast PWM with TOP = OCR1A (not ICR1). Since you are also using setting OC1A output for PWM with COM1A1, this will result in an OC1A remaining high.
As mentioned already, if you want to configure timers in the Arduino environment, you should do it from scratch with = instead of |=.
theusch wrote:
And, for all I know, more might be run after setup()
From Arduino's main.cpp: Code:
#include <Arduino.h>
int main(void)
{
init();
#if defined(USBCON)
USB.attach();
#endif
setup();
for (;;) {
loop();
if (serialEventRun) serialEventRun();
}
return 0;
}
JJ