I want to have an interrupt that runs roughly 75 times a second to, among other things, handle some housekeeping and check for button presses.
As far as I can tell I have it set up correctly, but it always crashes at the same point:
RTI Fired @ 13
RTI Fired @ 26
RTI Fired @ 39
RTI Fired @ 53
RTI Fired @ 66
RTI Fired @ 79
RTI Fired @ 93
RTI Fired @ 106
RTI Fired @ 119
RTI Fired @ 133
RTI Fired @ 146
R
You can see it's firing roughly every 13ms as expected, then at around 159ms in it dies. I know it has to do with the Serial.print() routine conflicting with the interrupt, probably by being midprint when it fires again. If I up the baud rate to something like 57600 it runs fine. I understand why it dies where it does (outputting 15 characters @ 9600 baud takes ~13ms the same as the ISR fire rate).
I'd like to better understand what's going on and how to protect against it. This ISR will be running in a complex program and I need to ensure it won't cause other issues like this.
Here's the test code:
void setup()
{
Serial.begin(9600);
setupRTI();
}
void loop()
{
//nothing
}
void setupRTI()
{
//Use timer 5, output A (pin 44)
// initialize timer5
noInterrupts(); // disable all interrupts
TCCR5A = 0;
TCCR5B = 0;
TCNT5 = 0;
OCR5A = 833; // compare match register 16MHz/256/75Hz ~75.03Hz
TCCR5B |= (1 << WGM12); // CTC mode
TCCR5B |= (1 << CS12); // 256 prescaler
TIMSK5 |= (1 << OCIE5A); // enable timer compare interrupt mask
interrupts(); // enable all interrupts
}
ISR(TIMER5_COMPA_vect) // timer compare ISR
{
Serial.print("RTI Fired @ "); //print RTI fire time
Serial.println(millis());
}
I don't think I can use cli(); and sei(); since the serial routine would just enable interrupts anyway right?
Do I need to mask OCIE5A while critical things are running?