Electronic – Reading a 16-bit timer on an 8-bit MCU


Since an 8-bit MCU can't read the whole 16-bit timer in one cycle, this creates a race condition where the low-word can roll over between reads. Does the community have a preferred method of avoiding these race conditions? I'm currently considering stopping the timer during reads, but I'd like to know if there's a more elegant solution.

FYI, this is for a PIC16F690.

Best Answer

Windell's right, if you're talking about PICs, the datasheet (and hardware) already handle this for you.

If you're not using a PIC, the general method I use is to do this:

byte hi, lo;
word timer_value;

do {
    hi = TIMER_HI;
    lo = TIMER_LO;
} while(hi != TIMER_HI);

timer_value = (hi << 8) | lo;

What this does is to read the upper byte followed by the lower byte, and to continue doing so until the hi byte doesn't change. This readily handles the case where the low byte of the 16-bit value overflows between reads. It assumes, of course, that there are no side effects from reading the TIMER_HI register multiple times. If your particular microprocessor doesn't allow that, it's time to throw it out and use one that isn't quite as braindead. :-)

This method ALSO assumes that your timer isn't changing so rapidly that you run the risk of overflowing the low 8 bits within a processor fetch cycle or two. If you're running a timer so fast (or a microprocessor so slow) then it's time to re-think your implementation.