0

I'm trying to use timer3 on an Arduino Mega 2560 in CTC mode. However, enabling CTC disables the code entirely.

Here is the function I call in setup() to setup the times.

void SetupInterrerupt() {
  cli(); // Disable interrupts

  // Setup timer
  TCCR3A = 0;     // set entire TCCR3A register to 0
  TCCR3B = 0;     // same for TCCR3B

  // Setup compare match register
  OCR3B =  CMP_FAST; // CMP_FAST = 40

  // turn on CTC mode:
  TCCR3B |= (1 << WGM32); // Commenting out this line makes the code work
  // Set CS10 and CS12 bits for 1024 prescaler:
  TCCR3B |= (1 << CS30) | (1 << CS32);
  // enable timer compare interrupt:
  TIMSK3 |= (1 << OCIE3B);

  sei(); // Enable interrupts

  Serial.println("Timers enabled");
}

And the interrupt vector.

// Timer 3 Interrupt
ISR(TIMER3_COMPB_vect){//timer1 interrupt 1Hz toggles pin 13 (LED)
  // do stuff...
}

As is, the interrupt doesn't execute at all. As noted in the code, commenting out "TCCR3B |= (1 << WGM32);" actually executes the interrupt, except the frequency is more like 1Hz instead of 720.

I'm using the arduino-lmic library, as well as some other data structure libraries. I don't think they use any timers, but since lmic is designed for Uno's, I figured that using timers 3 and up would be fine.

I'm a little rusty on my timers unfortunately. Is anyone able to spot my mistake?

Thanks.

1 Answer 1

1

I think your problem is that you are using the wrong "TOP" counter value register.

OCR3B =  CMP_FAST; // CMP_FAST = 40

should be:

OCR3A =  CMP_FAST; // CMP_FAST = 40

I am not too familiar with the workings of the AVR times, but according to the datasheet:

In Clear Timer on Compare or CTC mode (WGM22:0 = 2), the OCR2A Register is used to manipulate the counter resolution. In CTC mode the counter is cleared to zero when the counter value (TCNT2) matches the OCR2A. The OCR2A defines the top value for the counter, hence also its resolution.

(Note: it only mentions the register for timer 2, but the same holds true for all the timers in the same class, including timer 3).

Since OCR3A is zero it never triggers a match. And since there is only one counter (TCNT3) which gets reset to 0 on a match, there can only be one register to compare to, and that is the "A" register. The "B" register appears to be redundant in CTC mode.

You may also need to switch to the COMPA vector (I am not sure on this one TBH)

3
  • Thanks for the response! Unfortunately, that didn't seem to work. Switching from OCR3B to OCR3A doesn't change the behavior. Switching to the COMPA vector causes the Arduino to reboot continuously (I suspect whenever the interrupt occurs). Enabling TCCR3B |= (1 << WGM32); simply disables the timer again. I think I've also tried using timers 0-2, to no avail.
    – Jordan Sim
    May 1, 2019 at 11:55
  • Maybe you should switch to using a library to manage it for you instead. I'm sure there's some variation on the TimerOne library for Timer 3.
    – Majenko
    May 1, 2019 at 12:17
  • 1
    Besides changing OCR3B to OCR3A, you also need to change OCIE3B to OCIE3A, and TIMER3_COMPB_vect to TIMER3_COMPA_vect.
    – Gerben
    May 1, 2019 at 13:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.