I have working code but just wanted to ask if anyone knows of a more elgant way to handle a problem I've noticed & had to write special code to handle...
I'm using INT0 to capture governor trigger events from a hall-effect switch... I have 16-bit Timer1 running with a prescaler of 1... I increment an OVF_Counter variable whenever Timer1 rolls over, and clear it to zero within the INT0 ISR.. where I save the Timer1 value at each event. I then calculate an elapsed number of Timer1 counts based on the time deltas as well as the number of OVF events that have occurred.
The problem I'm having, however, is dealing with the rare case in which the governor event happens at the exact same moment as the Timer1 rollover... and thus I enter the INT0 ISR code and grab a very low Timer1 value before the OVF Counter has had a chance to increment. I put in logic to try to catch this situation & compensate for it... but it just seems like a clumsy patch... and was wondering if anyone had any alternate suggestions to deal with this?
Here's a look at my current code: I enable ISR nesting with an sei() call in the middle of the code because the events happen so frequently that I run the risk of miss-timing other ISR events not shown here otherwise. I was going to take that part out so as not to distract from my main question... but just left it for completeness.
volatile signed char Timer1_OVF_Counter; ISR(INT0_vect) { // Locals static unsigned int CurrentTime=0, LastTime=0; signed char Timer1_OVF_Counter_Flag; // Extract 16-bit Timer1 Value CurrentTime = TCNT1; // Get OVF Count before enabling nested ISR's below Timer1_OVF_Counter_Flag = Timer1_OVF_Counter; // Reset Governor OVF Counter Timer1_OVF_Counter = 0; // Disable this Individual ISR to Prevent Recursion ClrBit(EIMSK,INT0); // Enable Global ISR's Allowing ISR Nesting sei(); // Handle Rare Occurence where Timer1 OVF's at Same Instant as INT0 Event & OVF_Counter Not Yet Incremented if ((Timer1_OVF_Counter_Flag==0) && (CurrentTime < LastTime)) { // Calculate Elapsed Timer Counts Assuming 1 Timer1OVF Must Have Occurred even though Value was Zero Gov.ETimeCounts = (unsigned long) CurrentTime - (unsigned long) LastTime + 0x10000; // Set OVF Counter back to zero since it would've been incremented to 1 after the sei() call above Timer1_OVF_Counter = 0; } // Normal Path else { // Calculate Elapsed Timer Counts Gov.ETimeCounts = (unsigned long) CurrentTime - (unsigned long) LastTime + (unsigned long) Timer1_OVF_Counter_Flag * 0x10000; } // Set Current Values to Previous for Next Entry LastTime = CurrentTime; // Now Re-Enable this Individual ISR cli(); SetBit(EIMSK,INT0); } ISR(TIMER1_OVF_vect) { // Increment Timer1 OVF Counter Timer1_OVF_Counter++; }
Thanks,
James