Page 1 of 1

TMR0

Posted: Mon Oct 12, 2009 1:20 am
by Ron
Hi,

I want to use TMR0 to count in 10ms increments. It seems to me that when I get to a section of my code I will read the current value in the TMR0_Count_Var and capture it. If my code must wait a minimum of 10ms before continuing and by counting in 10ms increments with TMR0 I may not get the full 10MS. TMR0 will have been counting for some amount of time before my code reads the TMR0_Count_Var, say 300us, so I would have only waited 9.7ms, not the full 10ms when the TMR0_Count_VAR increments.

Is this an accurate statement?

If yes, would I be better counting in 1ms increments and waiting for a count of 11ms to ensure I waited a minimum of 10ms?

Second question.

If I disable TMR0 in my code, and then restart it, does it start over from zero, or does it remember what time value that had counted and start from that value. This is not my count var, this is the time that had been counted while the TMR0 had been enabled.

Thank you,

Ron

Re: TMR0

Posted: Mon Oct 12, 2009 8:52 am
by Benj
Hello Ron

If the timer is configured correctly to timeout every 10ms then the interrupt macro should run every 10ms. This means your code will run every 10ms with a slight offset as to where it is in the interrupt macro.

The timer register is always counting once you have enabled it. The disable interrupt only stops the interrupt from firing and does not stop the counter from counting. If you need to stop the counter then you can do this by writing 0 to the timer config register using a C code block. eg t0con = 0; If you also need to reset the counter then you can do this by writing to the counter register again using C. eg tmr0 = 0;

Re: TMR0

Posted: Wed Oct 14, 2009 12:50 am
by Ron
Hi Ben,

I appreciate all the help.....

Now for more questions regarding TMR0. I looked at the tutorial description and saw that clock speed/ prescaler = Hz, but the math 3,276,800Hz/128 = 25600 (not 25).
Why does the 600 go away?

I want to run at 40MHz on an 18F and have 10ms counts. How can I achieve 100 counts per second?

Thank you,

Ron

Re: TMR0

Posted: Wed Oct 14, 2009 9:11 am
by Benj
Hello Ron

(((3,276,800Hz / 4) / 256) / 128) = 25

3,276,800Hz - Clock Speed
4 - Internal Clock Divider
256 - Timer count register
128 - Prescaler

I have been able to get a timeout rate of 200hz by using the following values for timer 0.

Clock Speed - 40MHz
PreScaler - 1:256
Timer offset = 61.

To allow this to work at the right frequency you need to add the following C code to the end of your interrupt service macro.

tmr0 = tmr0 + 61;

You can turn the 200hz into 100hz by adding a count value and seeing if the count value is 1. If it is then reset the counter, if not then increment the counter.

(((40,000,000Hz / 4) / 195) / 256) = 200.32

195 = 256 - 61

Re: TMR0

Posted: Wed Oct 14, 2009 9:20 am
by Steve
If you require exactly 10ms, you'll need to use a crystal that divides appropriately - the 19.6608MHz crystal would work. a 1:64 prescaler would make it interrupt at 300Hz. You would just need a global variable to count up within the interrupt macro and whenever it gets to 3, reset it to zero and do whatever you wanted to do at the 10ms interval.

Re: TMR0

Posted: Wed Oct 14, 2009 3:34 pm
by Ron
Hi,

Thank you Steve and Ben.

Quick question..... x2

How long does it take to process Var = (Var + 1) + (return time from the TMR0 routine) to the main application.

40MHz 18F
20MHz 16F

At prescalers of 16 (18F) and 8 (16F) I hit the 10ms exactly. I am trying to determine at 400us TMR0 counts how much time if left remaining to solve my logic.

Thank you,

Ron

Re: TMR0

Posted: Wed Oct 14, 2009 4:11 pm
by Benj
Hello Ron

If your using a timer interrupt then as long as the interrupt macro is not as long as the timout period then your interrupts will always be exactly in sync.

Eg if your interrupt period is 100ms then as long as your interrupt macro code is less then 100ms then your interrupt will be 100% spot on every time.

A var = var + 1 should translate into a single instruction or 4 clock cycles if the variable is a byte.
The return instruction would again be a single instruction or 4 clock pulses.

Re: TMR0

Posted: Thu Oct 15, 2009 12:48 am
by Ron
Hi,

I will be Incrementing a VAR using TMR0, when the VAR reaches 255 and then Increments again will it roll over to zero or do I have to push a 0 into the var1?

Thank you,

Ron

Re: TMR0

Posted: Thu Oct 15, 2009 8:29 am
by Benj
Hi Ron

Yes any byte variable in Flowcode will rollover from 255 to 0 when incrementing and from 0 to 255 when decrementing.

Re: TMR0

Posted: Thu Oct 15, 2009 12:59 pm
by Ron
Hi Ben,

When the VAR that I am using to count "10ms increments" rolls over to zero I need to account for this. I expect the TMR0 INT to trigger anywhere from 1 - 3 times (depending on how much/which logic solves) per scan, I need to read up to 15 non consecutive eeprom addresses on some logic scans. So I am using this formula and was wondering if it is OK.

ALL the VARS in the example are BYTEs

P1 = P1 - (( P2 + 256) - P3)

In the above formula I am adding 256 (which is larger than a BYTE can hold) but the subtraction of P3 will ensure that the result (P1) will never be more than 255. This takes into account that the TMR0 INT might trigger 2 or 3 times before completing a complete logic scan. I may roll from 255 to 2 before my logic gets to the point where it looks at the number of 10ms increments that have ocurred since the last scan.

Is the above formula OK (all VARs as BYTEs) or must I change P1 from a BYTE to an INT.

Thank you,

Ron

Re: TMR0

Posted: Thu Oct 15, 2009 3:40 pm
by Benj
Hello Ron

P1 will probably need to be an int. This way you do not have to try and do any fancy calculations to ensure you have not rolled over the count value of 255.

Eg if you were using the following where P1, P2 and P3 are all equal to 5.

P1 = 5 - ((5 + 0) - 5)

Which would result in P1 being equal to 250.

If you used P1 as an int then

P1 = 5 - ((5 + 256) - 5)

Which would result in P1 being equal to 251.

Not 100% sure what you are trying to do with this.

Re: TMR0

Posted: Fri Oct 16, 2009 12:46 pm
by Ron
Hi Guys,

I have the TMR0 almost working. I am using the TMR0 to count out a "pause" command.

18F4620 running at 20MHz, prescale of 8 Flowcode tells me I am running at 2441.41. I thought the formula was 20000 / 8 = 2500?

1 / 2500 = .0004, do what Steve suggested and do this INT for 25 times, then solve my "pause count down logic". This should be exactly 10ms. When I run a 120 second pause the pause lasts about 122 seconds. If I take the Flowcode reported 2441.41 and do the math (1 / 2441.41) * 25 = 10.2ms. The extra .2ms would help explain why my pause command is not working properly.

What am I doing wrong with the math?

Thank you,

Ron

Re: TMR0

Posted: Fri Oct 16, 2009 2:01 pm
by Benj
Hello Ron

The maths to work out the frequency is as follows.

((clock speed / clock divider) / timer register) / prescaler = interrupt frequency

Filling in the values becomes.

((20,000,000 / 4) / 256) / 8 = 2441.40625 Hz

Re: TMR0

Posted: Wed Oct 21, 2009 3:02 am
by Ron
Hi,

I need help, I cannot get the expected results using TMR0 INT. Either I do not understand how it works, or I am not implementing it correctly, or both. Please correct me as I explain what I think I know.

I want to count 10ms time periods but need to use 20MHz for now (waiting on 40MHz crystals). I know that 18F4620 at 20MHz using pre-scale of 8 gets me frequency of 2441.41.

Time = 1/f if I remember correctly

1 / 2441.41 = .0004096

.0004096 * 25 (counts of TMR0 INT) = about 10.2ms

10.2ms * 100 = 1.02 seconds (easier to time LED on/off at 1 second intervals)

If I count each time I enter the TMR0 INT and I use a test block == 250. I have my TMR0 logic solve for Yes then every 250 times TMR0 is executed the logic I want to solve (every 1.02 seconds) should solve. Is this correct? I am toggling an LED ON/OFF

The logic is solving many times faster than I expect.

I have no idea where to go from here.

Thank you,

Ron

Re: TMR0

Posted: Wed Oct 21, 2009 6:59 am
by Steve
I'm guessing that your LED flashes 10 times faster than you thought it would...
.0004096 * 25 (counts of TMR0 INT) = about 10.2ms

10.2ms * 100 = 1.02 seconds (easier to time LED on/off at 1 second intervals)
You are multiplying by 25 and 100. So in your interrupt routine you should be counting up to 2500 (25 * 100), not 250.

Re: TMR0

Posted: Wed Oct 21, 2009 1:43 pm
by Ron
Hi,

Guess I need to go back to 3rd grade after I get some sleep.

Thank you,

Ron