简体   繁体   中英

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?

I'm not sure, but depending on the version of Arduino you use, the println call would be blocking. If you call it faster than it can complete in your ISR, the stack will overflow.

If you want higher resolution timing, maybe try differencing the getMicroseconds result in your Loop() . You should cycle in Loop() far faster than once per millisecond.

If you want to do something once per millisecond, capture a start microseconds, and then subtract it from the current microseconds in a conditional in your Loop() function. When you see more than 1000 do the task...

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM