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
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)
-
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– Jordan Sim2019年05月01日 11:55:56 +00:00Commented 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– Majenko2019年05月01日 12:17:11 +00:00Commented May 1, 2019 at 12:17
-
1Besides changing
OCR3B
toOCR3A
, you also need to changeOCIE3B
toOCIE3A
, andTIMER3_COMPB_vect
toTIMER3_COMPA_vect
.Gerben– Gerben2019年05月01日 13:50:26 +00:00Commented May 1, 2019 at 13:50