PDA

View Full Version : Not getting this timer thing.



Szczepaniec
- 29th July 2011, 01:57
I have been wrestling with the basic understanding of timers and based on some examples off the internet thought I finally had my hands around it until I started inserting code inside the timer loop. Why does this run at 1 minute when there is no "test" loop toward the bottom of the code but runs at 1 minute and 3 seconds when there is a test loop. It is my understanding that the timer should be running independent of the other things going on such as the test loop. I am running this on a 16F1827. Thanks for any insight anybody has.

Also, I got the base code from http://www.instructables.com/id/PIC-micro-Timer-Code/ and it is a good simple explanation. Is anybody aware of a equally simple explanation of a timer using interrupts?

Include "modedefs.bas"
DEFINE OSC 16
OSCCON=%01111010
test var byte
time var word
msec var byte
msec = 0
sec var byte
sec = 0
mint var byte
mint = 0
hour var byte
hour = 0

high portb.4
pause 500
low portb.4

T1CON.0=1 'starts the timer
'T1CON.0=0

Start:
TMR1H = 0 'resets the timer value's high byte
TMR1L = 0 'resets the timer value's low byte
'--and--
do
time.Lowbyte = TMR1L 'puts the timer's low byte in MyTime's lower 8 bits
time.Highbyte = TMR1H 'puts the timer's high byte in MyTime's upper 8 bits


if time > 40380 then
TMR1H = 0
TMR1L = 0
time = 0
msec = msec + 1
endif
if msec = 100 then
msec = 0
sec = sec +1
endif
if sec= 60 then
sec = 0
mint = mint + 1
endif

if mint = 60 then
mint = 0
hour = hour + 1
endif

if mint = 1 then
high portb.4
pause 500
mint = 0
low portb.4
endif
test = 0
do until test = 255

test = test +1
loop
loop

Szczepaniec
- 29th July 2011, 03:35
In the event that it matters to anybody helping, when I cut down the "test" count from 255 to 127, the overrun is 1.5 seconds or half the overrun when the test is counting to 255. Thanks again.

mister_e
- 29th July 2011, 09:01
Well, you cadd code overhead at the end... and you don't use interrupt. Change your last DO/LOOP for a PAUSE 10000.. you'll have 1 minute + 10 secondes.

You want to do something at each XYZ time without having to care of the main loop? use a timmer interrupt. Plenty code example in here.

Szczepaniec
- 29th July 2011, 12:10
Well, you cadd code overhead at the end... and you don't use interrupt.
I am not familiar with "cadd code" If you intended to say "copy code" then yes, I did copy some code in an effort to learn how it works.


Change your last DO/LOOP for a PAUSE 10000.. you'll have 1 minute + 10 secondes.
Pause does not do anything for me, I understand pause and the limitations of it. The do loop is not to add additional time, it was to see if giving the PIC another task within the timer would change the time which it did, but I don't understand why. This entire piece of code is nothing but to work with the timer and understand it. There is no purpose for it other than that. I am not trying to achieve a goal of timing one minute or one minute and ten seconds, I am only trying to learn exactly how the timers work.


You want to do something at each XYZ time without having to care of the main loop? use a timmer interrupt. Plenty code example in here.
At the end of the day I do want to use a timer interrupt for the project and there are many examples of code here. I have struggled in part because every example I have found has the code buried in code for buttons, LCDs, etc. I could not find a simple step 1, step 2, step 3 example that made sense to me. So, I decided to figure it out one step at a time. Step one was to figure out the timers and registers associated with the timers. The code I found on instructables.com was perfect for that and brought me to where I am now. However, it was my understanding that the timer should be ticking away almost without regard to the other things the processor is doing. I think my simple test indicates that something else is going on that I cannot wrap my head around. I don't think it does me any good to copy code from other timer projects without the understanding of how it works (or doesn't). If somebody could tell me where my thought process is wrong in this timer example I would be very grateful.

Bruce
- 29th July 2011, 13:19
Hardware timers will continue running once enabled. It runs on its own, in the background, until you disable it.

If you're in a loop reading the timer, checking for a value > x, the value you read indicates how long the timer has run.

When you insert the test loop, this wastes time, which adds to the timer count since it's still running while your code in the test loop executes.

So - the more code that executes before you read the timer, the larger the count will be. At least until it rolls-over back to 0.

The timer is also running during your PAUSE time. At 16MHz, with a prescaler of 1:1, Fosc/4 as the timer clock source, timer1 increments by 1 count every 250nS. Since timer1 is a 16-bit timer it will count from 0 to 65,535 then roll-over back to 0 and continue counting.

Here's a neat example showing how to use a timer to see how long PBP code takes to execute.
http://www.picbasic.co.uk/forum/showthread.php?t=365

Here's on using timer2 as a clock
http://www.picbasic.co.uk/forum/showthread.php?t=10571&p=70262#post70262

cncmachineguy
- 29th July 2011, 14:06
taking a stab at this:


I am not familiar with "cadd code" If you intended to say "copy code" then yes, I did copy some code in an effort to learn how it works.

I think Steve was saying add code. With that he is pointing out that you have added code overhead but don't use interrupt on the timer, so the added code slows the clock down. Adding the pause is just to illistrate this further.

And all that Bruce said. :)

Szczepaniec
- 29th July 2011, 14:28
So is the 3 seconds the test loop adds an accumulation of the timer1 count value above 40380 when the value is finally checked? I guess I didn't account for the overage if that is the case.

I did some more playing with timer2 last night and did the same test as I did with timer1. Regardless of what test loops I put in, the time appeared to stay the same. That had me looking for difference between timer 1 and 2. Is it fair to say the timer2 routine would also have an overage and is longer with the test loop but it isn't noticeable when timing with a stop watch?

Here is the timer2 code:

Include "modedefs.bas"
DEFINE OSC 16
OSCCON=%01111010
test var byte
PR2 = 249
time var word
msec var word
msec = 0
sec var byte
sec = 0
mint var byte
mint = 0
hour var byte
hour = 0
'pir1.1 match flag

tmr2=0
pr2 = 1

high portb.4
pause 500
low portb.4

'T2CON.2=1

t2con =%01111111
do
if pir1.1 = 1 then
pir1.1 = 0
msec = msec + 1
if msec = 1000 then
msec = 0
sec = sec +1
if sec = 60 then
sec = 0
mint = mint+1
endif
endif
endif

'test = 0
'do until test = 127
'test = test +1
'loop
if mint = 1 then
mint = 0
high portb.4
pause 500
low portb.4
endif
loop

cncmachineguy
- 29th July 2011, 14:45
YES!!! :):)
The test loop adds execution time, which causes your time before check to be longer.
There are prolly some differences in how you can use timer 1 and timer 2, but if they are set up as counters triggered by fosc/4, they will count the same.

You have a few choices in how to deal with getting accurate times. the first and always pointed at is to use interrupts. The second is to auto adjust the count while the program is running. to do this, once the timer is greater then target number, subtract target number from the CURRENT timer value. when you reload the timer, reload it with your reload value + the difference just calculated. Mind you, that is for a counter counting up. If using PR (as with timer 2) you can just load timer 2 with the difference. then it will count from adjusted number to PR value, instead of from zero to PR.

Did any of that make sense? Both methods are valid and useful depending on application. (Thanks PBP members for the auto correct idea)

amgen
- 29th July 2011, 17:37
Consider dt-ints and this structure.5806
don
amgen

Szczepaniec
- 29th July 2011, 18:50
I can attain the results I need through the Timer2 and with the serial comms I need to mix in, timer2 is probably the best way. Thanks to all who set me straight on this. I think I understand enough now to get me to the next item I don't understand.