Search code examples
c++timerarduinoavrarduino-c++

16-bit timer in AVR CTC mode


I'm trying to achieve that with an Arduino Uno board (ATmega328, 16 MHz). So I searched through the Internet and came up with something like this:

unsigned long Time=0;

int main (void)
{
  Serial.begin(9600);

  cli();

  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;

  OCR1A = 15999; // Compare value

  TCCR1B |= (1 << WGM12)| (1 << CS10); // Prescaler
  TIMSK1 |= (1 << OCIE1A); // Enable timer compare interrupt

  sei();

  while(1) {

    Serial.println(TCNT1);
  }

  return 0;
}


ISR(TIMER1_COMPA_vect)
{
  Time++;
  Serial.println(Time);
}

I'm trying to achieve a frequency of 1 kHz, so I'll be able to create intervals which are a couple of milliseconds long.

That's why I chose the comparison value to be 15999 (so 16000-1) and the prescaler to be equal to 1, so I get (at least what I believe to be the right calculation):

Frequency = 16.000.000 MHz/16000 = 1000 Hz = 1 kHz

The problem now is that, even though the Serial.println(TCNT1) shows me numbers counted up to 16000, back to zero, up to 16000, back to zero,..., Serial.println(Time) just counts up to 8, and it just stops counting although TCNT1 is still counting.

I thought about some kind of overflow somewhere, but I could not think about where; the only thing I came up with is that the comparison value might be too big which is -as I think - obviously not the case since 2^16 -1=65.535>15999.

If I, for instance, make the prescaler, let's say 64, and leave the comparison value, Time counts as expected. So I'm wondering: Why does ISR() stops getting called at a value of 8, but works when bringing up the prescaler?


Solution

  • It seems like the resolution of the timer was too much for my Arduino Uno (16 MHz). Chosing a lower resolution (i.e higher compare value) fixed the issue for me.