PDA

View Full Version : Timers, oscillators, cycles... need basics please



flotulopex
- 23rd October 2006, 18:10
Hello,

I'm starting with TMR0 interrupts handling and I'm completely lost in how to calculate all different timings.

Please correct me if I'm wrong!!!

As far as I got up to now, I gathered following informations:
a) the main PIC's "clock" is equal to the oscillator frequency;
b) at 4MHz, my PIC will handle around 1'000'000 instructions per second;
c) without Prescaler, 1 instruction will last 1us;
d) with Prescaler set to "1:4", 1 instruction will last 4us(?);
e) TMR0 will count from 0 to 255;
f) the PIC will generate an Interrupt when TMR0 reaches 255.

My questions are:
g) how do I know how many cycles this or that instruction needs?
h) how do I calculate the time for a TMR0 overflow?

Actually, I'm very confused and all documentation I have don't explain clearly how it works starting from the very beginning.

Thank you for your help.

ErnieM
- 23rd October 2006, 18:40
My questions are:
g) how do I know how many cycles this or that instruction needs?
h) how do I calculate the time for a TMR0 overflow?


g) Unfortunately the answer is “it depends.” Best way is if you think you are cramped for instruction cycles is to use a spare pin, set it before some code, reset after. Then you can use an oscilloscope to time how long it takes. You could also do this with the simulator in MPLAB, but the first way is probably quicker to do.

h) TMR0 overflows when the count goes from 255 back to 0. If you originally reset the timer, then hit it with the sys clock at the instruction rate, through the prescaler, the overflow time is:

instruction rate (sec) * prescaler (pure number) * 256 (pure number) = overflow rate

So with your 4MHz sys clock (1us rate) you’ll overflow:

1us * 4 * 256 = 1024 us = 1.024 ms

If instead you set TMR0 to some value, you can change this overflow time. If you set TMR0 to N, the time becomes:

instruction rate * prescaler * (256 – N) = overflow rate

So if you wanted a delay of 1.000 ms, you could try presetting N to 6:

1us * 4 * (256 - 6) = 1us * 4 * 250 = 1000 us = 1.000 ms

The exact time may be off a instruction or so as TMR0 needs some time to be updated (so don’t try this if you are accumulating the time in something like a real time clock).

flotulopex
- 23rd October 2006, 21:07
Hi ErnieM,

Thanks a lot for your quick reply!!!

I was just taking this the wrong way - now it looks much more comprehensive to me.

I'll grab a peace of paper, a pen, my calculator and do some exercices based on your informations.

In fact yes, I want to program a real-time clock based on examples from Melanie and others so the time used by some instructions is crucial.

Thank you again.

ErnieM
- 24th October 2006, 18:33
OK, so for a RTC you need some sort of precision and regularity, as things like a single instruction cycle ambiguity can kill you in the long term.

A clock requires excellent long term stability, but surprisingly, short term instability may be acceptable. I have something in mind like an alarm clock where if it rings at 7:00:00 AM or 7:00:02 AM it makes no difference.

Here’s what I mean: say you desire a 1 second “heartbeat” in your code to update the seconds indicator of the clock. You can use the 1MHz instruction rate into TMR0 with a 256 prescaler to generate an interrupt every .256ms. OK, you might get it a little faster or a little slower, but the important thing is you get them with a long term average (accuracy) of once every .256 ms.

So you count interrupts to see if a second has transpired. A second with .256ms rate lasts… dang! 3906.25 counts. OK, not so bad… make an interrupt routine fired by the TMR0 overflow, when it fires add 1 to a counter (call it TICKS), when the TICKS gets to 3906 reset it, AND add 1 to the SECONDS variable.

This by itself would be OK for the short haul, but it has an error of 1ms every 4 secs. We can correct for that: note 4 seconds takes 3906.25 x 4 = 15625 counts, but when TICKS increments 4 times we’ve only counted 3906 x 4 = 15624. We’re one count short! But ONE, not one point something, but exactly integer ONE.

Cool. So, use the same TICKS counter, add 1 to SECONDS at TICKS = 3906, 7812, 11718, and 15625, and when TICKS hits 15625 also reset TICKS.

You’ve just traded a short term error of .75ms for a long term error of zero.

(Of course, this all depends on the instruction rate being 1.000000MHz, so use a crystal to clock this thing.)