I'm trying to have an interrupt that runs at a particular interval, regardless of how long the main loop takes to run. The purpose of this interrupt is to check at a regular interval whether a condition has been met, and if so activate a pn change interrupt to be able to run when (at some future time) a pin change occurs. Once the timer interrupt has fired in circumstances where the condition has been met I want to turn the timer off again so I don't get further calls of the timer interrupt and don't waste power/processing capacity/... servicing a timer and associated interrupt which are no lonegr needed (until some much more distant future time, when I turn the timer back on when other conditions are met).
I do NOT want the timer doing any automaticpin toggling for PWMing an output wire.
Is the use of code shown below correct?
I read over the gammon article on timers and the one on interrupts, but while there were examples Icouldn't see much about explicitly starting and stopping the timers.
I also read over the 328p's datasheet, about the registers involved, but it only gave examples of tiny snippets fo code writing to the registrs, not of actually starting and stopping the timers. It also warned of:
a) some special conditionsneeded whenever accessing a 16 bit (2 byte) register, I'mnot sure if GCC handles these automatically or not?
b) some cases in which when OCR1A gets set the timer's counted value may have already ascended above it, and one wouldn't get another timer interrupt for absolutely ages (I trigger at 250 in CTC mode, if this happened it would go up to >65K before relooping and triggering at 250).
Is my code proof against those risks?
Please note that the timer starting function always gets called, in my use of it, from inside a different ISR, so interrupts are disabled at the time it is set up.
Code below, thank you.
Please "scroll" to the side in the code to see my full comments which further point out my questions.
void StartTimer(){ //this gets called within an ISR which is not triggered by the timer
TCCR1A = 0; // apparently this is how to start the timer
TCCR1B = bit(WGM12) | bit(CS11); // supposedly sets CTC mode and selects a pre-scaler
OCR1A = 250; // derived by trial and error to set how long I want to wait from the timer starting until the timer driven interrupt fires, it is written like this and 250 is very much a constant, I could do it by #define or by a const uint8_t
TIMSK1 = bit (OCIE1A); //sets up an interrupt for when the timer's internal value reaches the OCR1A value and resets?
}
ISR (TIMER1_COMPA_vect){
//do stuff to assess what value "situation" has
/*
stuff
*/
if( (situation==1 ) && (PCICR == 0)){ //situation met, and pin change interrupt is off
//do various stuff here
/*
stuff
*/
PCIFR |= bit (PCIF0); //clears pin change interrupt's flag, thereby forgets about any which have already occured but not been serviced
PCICR |= bit (PCIE0);//re-enables pin change interrupt, I know these pin change interrupt register writing actions work properly
TCCR1B = 0; //I think this stops the timer? Does it indeed, or does it just stop the interrupt? Does this stop the timer? and does it reset the timer's count to zero? I tested by adding some port manipulation in this ISR for debug purposes and watching on an oscilloscope, it certainly looked like the ISR stopped re-occuring once the situation condition was met
}
}
ISR (PCINT0_vect ){
//do various stuff
/*
stuff
*/
PCICR&=0b11111110; //this disables the pin change interrupt, I know this works
StartTimer(); //will this timer, started like this always start the timer at zero? Or could it start from any arbitrary value depending on where it got to last time it was stopped? Can it end up starting from values >OCR1A, which would be a serious problem as that way the pin change interrupt wouldn't get checked for whether to re-enable for far too long an interval
}
Or should I perhaps take the OCR1A out of the StartTimer(); function, and set OCR1A only once, during the program's initial setup? Should I be accessing any other registers to reset the timer 1's timer variable somehow at the time I try to stop the timer?
Thanks