[SOLVED] Understanding TIMER2 behavior?

I'm working on a project that requires me to user Timer2. However, when I do my testing it seems to run 4 times faster than I asked.

In order to debug this I wrote a small program to compare using Timer2 to using Timer1. The program simply sets up a timer to run every 1 millisecond and increment a variable "ticks" by 1. My loop delays 1 second (1000ms), copies ticks to a local variable, zeroes out ticks, and then prints out copied value to my LCD.

When run using Timer2 its gives 247 to 250 as values.
Run using Timer1 (by commenting out #define USE_TIMER2 I get 1013 to 1014 which is about what I expect.

I'm sorry but I pressed the wrong key and this posted without my code. I'll add it in just a minute.
Thanks for your patience.

Here is my code it used an I2C LCD as output.

Interrupt.ino (2.54 KB)

While I posted the entire program in my previous post
My code snipplets for the timers is this:

// code copied from http://www.8bit-era.cz/arduino-timer-interrupts-calculator.html
#ifdef USE_TIMER2
  // TIMER 2 for interrupt frequency 1000 Hz:
  cli(); // stop interrupts
  TCCR2A = 0; // set entire TCCR2A register to 0
  TCCR2B = 0; // same for TCCR2B
  TCNT2  = 0; // initialize counter value to 0
  // set compare match register for 1000 Hz increments
  OCR2A = 249; // = 16000000 / (64 * 1000) - 1 (must be <256)
  // turn on CTC mode
  TCCR2B |= (1 << WGM21);
  // Set CS22, CS21 and CS20 bits for 64 prescaler
  TCCR2B |= (1 << CS22) | (0 << CS21) | (0 << CS20);
  // enable timer compare interrupt
  TIMSK2 |= (1 << OCIE2A);
  sei(); // allow interrupts
#else
  // TIMER 1 for interrupt frequency 1000 Hz:
  cli(); // stop interrupts
  TCCR1A = 0; // set entire TCCR1A register to 0
  TCCR1B = 0; // same for TCCR1B
  TCNT1  = 0; // initialize counter value to 0
  // set compare match register for 1000 Hz increments
  OCR1A = 15999; // = 16000000 / (1 * 1000) - 1 (must be <65536)
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS12, CS11 and CS10 bits for 1 prescaler
  TCCR1B |= (0 << CS12) | (0 << CS11) | (1 << CS10);
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
  sei(); // allow interrupts
#endif

While the interrupt is simply

// The interrupt run every 1ms and will simply increase ticks count by one
#ifdef USE_TIMER2
ISR(TIMER2_COMPA_vect)
#else
ISR(TIMER1_COMPA_vect)
#endif
{
  ticks++;
}

From the attached Interrupt.ino

TCCR2B |= (1 << WGM21);

WGM21 is on TCCR2A.

You are actually setting the CS21 bit on TCCR2B and winding up with a 256 prescaler.

When trouble shooting these timer problems, it is always best to print out the values of the registers to confirm that you have what you think you have.

These comments are very unhelpful

  TCCR2A = 0; // set entire TCCR2A register to 0
  TCCR2B = 0; // same for TCCR2B

because each bit in those registers has a special purpose but you have not recorded that.

Have you studied the Atmel datasheet - for the Atmega 328 if you are using an Uno. It has all the details.

...R

Thank you cattledog!

Setting TCCR2A |= (1 << WGM21);
instead of TCCR2B |= (1 << WGM21);

works fine now.

And yes I did read (and often) the datasheet, just need better glasses :slight_smile: