PDA

View Full Version : Timer Questions



rwskinner
- 24th February 2006, 02:09
I'm using PBP244 and have not ever played with timers or interupts yet.

My project is a simple watchdog timer for an external device. The external device sends serial commands to the 877A to reset the count down timer. If for some reason, this command is not seen in xxx seconds, then the pic resets the external device.

All my serial code is working well and it's time for me to install the timer functions.

I assume, that the best way to acheive this would be to have a Word var that would be incremented by 1 each time a preset timer fires an interrupt. A predetermined serial command would Zero the word var and the process would repeat. If no command was received, the word var would increment to a point that causes my pic to perform the external device reset.

How would one have an interrupt fire approx once per second on a 877A @ 8 mhz? Any help would be much appreciated.

rwskinner
- 25th February 2006, 14:39
Wow, Maybe the question was phrased incorrectly.

I now have an interrupt being fired by timer1 at approx. 1 second. I had to keep guessing at the value I loaded into the timer until I got close to what I needed.

I would rather understand the formula for determining how to get the proper value to load into the timer. Can anyone shed some light on this?

How to take the clock speed, determine the prescaler value, and the counts that need to be preloaded in order for the timer to overflow and cause an interrupt.

BigWumpus
- 25th February 2006, 17:00
As an example:

Timer1 (16 Bit) is used and feed with:

I use an 4MHz resonator.
f_OSC/4 (this is the "normal" countrate für a PIC!)
Presacler: 1/8 (Set in T1CON or so)

Then I get 4.000.000 / 4 = 1.000.000
/ 8 = 125.000 counts per second

So, i can handle up to 0,5 seconds (62500 counts) in this 16-bit-timer.

I load the Timer1 with -62500 (=0BDCh), clear TMR1IF and start TIMER1.

When it reaches 0000, the TMR1IF is set, I will stop TIMER1, count down my WORD-variable in order to build the watchdog-timer, clear the TMR1IF and start TIMER1 again.

If you are using higher speeds, then the numbers must be changed.

It is quick-n-dirty !

Bruce
- 25th February 2006, 19:24
With an 8MHz osc, Timer1 will increment by 1 every 500nS with a prescaler
of 1:1.

It's a 16-bit timer so it can count from 0 to $FFFF or 0 to 65,535. Once it
reaches 65,535 and rolls-over back to 0, it will generate the interrupt if the
interrupt is enabled.

That means you have 65,536 Timer1 ticks before roll-over. 65,536 * 500nS
= 32.768mS before each Timer1 interrupt.

1 second/32.768mS = 30.517. Once Timer1 has over-flowed 30 times, you
know a 30 * 32.768mS (0.98304 seconds) period has expired.

If 0.98304 seconds is close enough to your "approximate" period of 1 second,
then you could do something simple like this;

Setup Timer1 with a 1:1 prescaler, clear Timer1, start the timer. Then count
each over-flow by monitoring the Timer1 interrupt flag bit. PIR1.0.

Just monitor PIR1.0. Once this flag bit is set, clear it, then increment your
variable;


IF PIR1.0 THEN
PIR1.0 = 0
MyVar = MyVar+1
ENDIF

If MyVar = 30 & no serial data has been received from your external device,
then reset the external device.

If the external device responds before MyVar = 30, then reset MyVar to 0 to
restart your countdown.

You can do this without interrupts by just watching the Timer1 interrupt flag
bit. This flag bit is automatically set each time Timer1 rolls-over, whether you
have the Timer1 interrupt enabled or not.

If you need more time, then just use the prescaler.

Example: Setup Timer1 prescaler to 1:8. This gives you 8 * 65,536 * 500nS
(8 * 32.768mS) for 0.262144 seconds before the flag bit is set. You would
then only need to increment your variable to 4 (4 * 0.262144 = 1.048576
seconds) for your approximate 1 second period.

You only need a 1 byte variable for the over-flow counter, your program
never gets interrupted while it's doing other things, and you'll be darn close
to your 1 second period before resetting the external device.

If you need better precision, you can let the timer free run and roll-over x
number of times until the roll-over count is just short of your required time
period.

After x number of roll-overs, stop the timer, and load it with a value that will
cause the last roll-over at the remaining time required for your 1 second
period.

rwskinner
- 26th February 2006, 01:16
Thanks to all, this helps tremendously.

I have it firing to the second over a 30 minute period so I must have done something right.

BaudRates.... I normally use either 4 or 20 Mhz clocks and this is my first time with an 8 mhz.

With the 8 mhz, I can do 9600,N81 Easy and reliable, but at 19,200 N81, I get lots of errors and garbage.

Is the 8 mhz to slow to do 19,200 reliably or is it something else maybe? I'm not doing much in the program at all, mainly just a SerIn2 with a 50ms timeout, after the timeout, I just go back to serin2 and wait.

TIA,
Richard

rwskinner
- 26th February 2006, 04:40
I found a chart on the net. It pretty much states that 8 mhz is too slow for 19,200 so I jumped to a 20 mhz and all is well. Even recalibrated my timer routines.

Thanks for all the help here.

Richard

rwskinner
- 1st March 2006, 04:20
Okay, See if I learned anything.

OSC 20

20 mhz / 4 = 5 mhz
1 second / 5,000,000 = 0.0000002

Each tick is 0.0000002 seconds

So, I would need 50,000 ticks to make it fire 100 times per second.

Since the timer counts up to 65535 and we roll over I would do this....

65,535 - 50,000 = 15535

Preload the timer with 15535 then
0.0000002 x 50,000 = 0.01
So the Timer would fire every 100 times per second

Why then do I have to preload the timer with 15543 to make it dead on? Is this just a difference in osc frequency.

Bruce
- 1st March 2006, 15:17
65,535 - 50,000 should be 65,536 - 50,000. Your load value would be 15536.
It takes 65,536 cycles (0 to 65,535 + 1 additional cycle) for the 16-bit
overflow or roll-over from 65,535 back to 0.


Why then do I have to preload the timer with 15543 to make it dead on? Is this just a difference in osc frequency.
Because the timer is still counting while you're doing things after it rolls-over.

You need to compensate for time passed (timer counts) while your program is
doing something after the roll-over. The timer is still counting during this time
frame.

You can either write an adjusted value to the timer, or simply "add" your real
value to the existing count already held in the timer registers.

Adding the real value to the existing timer count is the prefered method as
long as your program doesn't tinker around long enough to where adding to
the count would cause immediate over-flow after the add.

BigWumpus
- 1st March 2006, 16:03
If the time is not precise enough for you, you can use CCP1 in order to restart Timer1 automatically.
But I think it is to heavy for a beginner.

rwskinner
- 1st March 2006, 17:44
Oh, the time is plenty close enough for what I'm doing. I just asked so I could learn and take notes.

Thanks agin for the help...