I seek to call an ISR routine after a fixed time of 400us. This action needs to be done every now and then (in the range of 0.8-3.0ms). For that matter, I thought I'd set timer2 to CTC mode, use OCR2A to set some TOP value for 400us and let the timer call the ISR routine after 400us. Within the ISR I would then stop the timer from triggering interrupts, until I need to count to 400us again, where I would activate the timer interrupt again.
This works, as expected, except for the fact, that after activating the interrupt for OCR2A again, it instantly triggers. The code below, produces a 1ms alternating signal, instead of 1ms+400us.
My question is, am I on a good way with this, or should I use the overflow ISR and preload the timer? Or any other method? The problem is, that after the 1ms waiting time in the main loop, I'd expect the counter to count from 0 to 100, meaning 400us. However on an oscilloscope I see the pin toggle each 1ms.
uint32_t timestamp;
void setup() {
Serial.begin(115200);
pinMode(9, OUTPUT);
cli(); // disable global interrupts
// Timer2 for counting (to release the pin)
TCCR2A |= (1 << WGM21); // CTC mode, clear timer on compare match
TCCR2B |= (1 << CS22); // Prescalar 64
OCR2A = 99; // ticks, before ISR is called
TIMSK2 |= (1 << OCIE2A); // enable timer compare interrupt
TCNT2 = 0x00; // set the timer to 0
// counting time[s] = (OCR+1)/(F_cpu/prescalar)
// 99 = 400us | 124 = 500us
sei(); // enable global interrups
timestamp = micros();
}
void loop() {
uint32_t now = micros();
if (now - timestamp > 1000) {
timestamp = now;
cli();
TIMSK2 |= (1 << OCIE2A); // enable timer compare interrupt
sei();
TCNT2 = 0x00;
}
}
ISR(TIMER2_COMPA_vect) {
// Serial.print(F("Here\n"));
PORTB ^= 2; // set pin 9 high again
// TCNT2 = 0x00; // reset timer for testing
// deactivate the counter
cli();
TIMSK2 = 0x00; // unlink the ISR from timer
sei();
}