Larry Bradley wrote: > G'day. In one of my projects, I need to know the elapsed time quite > accurately (assume it is a clock display - it isn't but the clock is > easy to talk about). In conjunction (I have been doing the programming, he has been doing the hardware and testing) with ke Neehr ( neehr@swipnet.se ), I have been working on such a project. Actually, it *is* a clock. Sooner or later it will be published by way of reference. May I firstly suggest, as firmly as possible whilst remaining courteous, that you *forget* any approach using modification of the timer/ counter register, particularly in an interrupt loop or whilst using the prescaler. It's probably possible, but a foolish enterprise. Set prescale to 8. You do *not* need interrupts, but need to poll for timer overflow. With a 4 MHz crystal, you will have an overflow every 2.048 milliseconds. If OTOH, you choose a 4.096 MHz crystal, you will overflow every 2 ms exactly. This is what ke chose to do (I was going to use software correction as follows at length). For the clock application, four digits were to be multiplexed, so the poll loop is executed once for each digit, giving an outer loop cycling every 8 ms (or 8.192 ms with the 4 MHz crystal). This loop decrements a (single byte) counter from 125 and rolls over exactly each second. Tens of seconds, minutes etc. are counted accordingly. Obviously, an 8 ms cycle could have been achieved directly with a prescale of 32. Do not get confused about a polling loop. The "inside" polling loop allows nearly 2 ms to perform necessary functions in all the loops combined *on average*. In fact, the complete chain of counters has by the same token, nearly 4 ms to do its work, that is, 4000 instructions, because as well as the 2 ms from one counter rollover to the next, it can safely *ignore* the rollover by nearly another 2 ms as long as this happens no more often than alternate cycles. Of course, this happens in the event, far more infrequently. The sequence of the loop is to wait for the rollover, perform the timing-critical operation (multiplex to the next display digit), then do any other housekeeping (counting the seconds, tens etc...) for up to about 1.8 ms. and go back to the wait (poll) for rollover. Because ke simply used the 4.096 MHz crystal, I never got around to the time correction code for the 4 MHz one. It goes however as follows: We are accumulating 8,192 s increments. Let's increment them in two parts. The 8 ms part is simple, because 125 of them make a second, and that count can be performed in a single byte. How to manage the 192 s parts? Well, 192 is conveniently 3 times 64, so let's count those s in lots of 64. This is real neat, since 128 of these lots of 64 actually equals 8192, which is in fact, a whole increment or "tick" for the next loop. And we add three at a time. The procedure goes like this: 8,192 s rollover: counter1-- If counter1 == 0 then (process_seconds; counter1 = 125) counter2 += 3 If counter2 >= 128 then (counter2 -= 128; counter1--) If counter1 == 0 then (process_seconds; counter1 = 125) Note that in PIC assembler, "If counter2 >= 128 then" reads BTFSC counter2,7 and "counter2 -= 128" in this particular case reads BCF counter2,7 .. and of course you would use DECFSZ to combine the decrement and test on counter1. There are various ways to roll/ unroll the above algorithm so that process_seconds is performed inline and last, rather than as a call, since it could never be called twice in the one loop. This means that the *resolution* and jitter of the procedure is still set at 8,192 s. -- Cheers, Paul B.