Timer0 and obtaining desired interrupt frequency/delay.

Tips, Tricks and methods for programming, learn ways of making your programming life easier, and share your knowledge with others.

Moderators: Benj, Mods

Post Reply
medelec35
Matrix Staff
Posts: 9520
Joined: Sat May 05, 2007 2:27 pm
Location: Northamptonshire, UK
Has thanked: 2585 times
Been thanked: 3815 times
Contact:

Timer0 and obtaining desired interrupt frequency/delay.

Post by medelec35 »

As you may be aware, it is not easy obtaining desired interrupt frequency as there a few
factors involved main one being target oscillator frequency.
In this example I am using EB006 programming board, EB005 LCD Eblock and EB003 Sensor board Eblock.
I would like to set timer0 interrupt so it triggers every 100 microseconds. That way I can use
timer0 for timing. If interrupt has been triggered 5 times then I know that 100x5 = 500us has
elapased. This could be useful for timing pulse durations because it keeps the maths simple.

Just a bit of backgound information regarding timer0 interrupt.
When timer0 interrupt is first activated the tmr0 register is set with 0. The prescaler will
determine how many source edges will increment the TMR0 register value by 1. Each edge is
derived from the target oscillator/4.

E.g If prescaler is set to 1:2 then tmr0 (tmr0l with 16 bit timers) is increased by 1 when
osc/4 has pulsed 2 times.
If target oscillator is set to 20MHz then tmr0 will increase by 1 at a frequency of 20x10E6/4/2 =
125000 = 2.5MHz
The timer interrupt is not triggered until tmr0 rolls over. i.e is tmr0=255, then 1 is added so
tmr0 goes from 255 to 0
Then that is the point timer0 macro on your flowchart is accessed.
This means the interrupt frequency = 2x10E6/4/2/256= 9765.625Hz The total time taken to do this
is 1/9765.625 = 102.4us.
Close, but not close enough. The way to increase the interrput frequency is either change the
prescaler or oscillator frequency or when tmr0 is changed from 255 to 0 so timer0 macro is
accessed, load tmr0 with a higher value than 0 so that means rollover will take place sooner..
Determing this tmr0 pre-loaded value is what the posted flowchart is going to achieve.
When hardware is ran, the top line of display will the ADC value of pot and how much tmr0 is going to be increased or decreased by.
Depending on pot (connected to ADC1) the amount tmr0 will alter by will be either +1, +5, +10 or -1, -5 or -10. Just like coarse or fine tuning. If pot is left in its central position, then tmr0 will not alter.

Code: Select all

ADC            tmr0 Adjust by
251 - 255          +10
211 - 250           +5
151 - 210           +1

121 - 150          No Change

91 - 120            -1
41 - 90             -5
0 -  40            -10
Bottom line of display will either show tmr0=+ then a value that is currently used for preloading tmr0 register or will show 'No Val Req' since that means tmr0 is curreny loaded with 0.
Going back to the 100us thats required, you will need a scope (for reading pulse duration or frequency) or multimeter that can read frequency.
Timer0 interrupt will have to be set at a value that's lower than the required frequency (but as near to frequency as possible). Desired frequency = 1/Time delay = 1/100us = 10KHz.
With oscillator set to 19.66MHz then the nearest frequency just below 10KHz = 9600Hz.
Set pot in the middle. Now compile to chip then measure frequency or duration between pulses between RA2 and ground. On my hardware I am measuring 9.13 KHz when tmr0 is preloaded with 0. Moved the pot so value is incrementing, and watching the frequency on the meter at the same time. When tmr0 was preloaded with 24, the meter displayed 10.01KHz, which is good enough for my application.
Now I know at the very beginning of timer0 interrupt macro I have to place a Cblock with:

Code: Select all

tmr0=+24;
in order for timer0 to be accesed evey 99.9uS.
IMPORTANT. I would not recommend letting value of tmr0 go too high. If over 250 for example and with prescaler on its lowest value, then hardware could stop functioning since interrupt macro is accessed too fast, leave little process time for the rest of the program.

Conclusion: The best way to do this if you want a precise delay: Before creating any more flowcharts.
1) Decide on the delay you require.
2) Load the the attached flowchart, and change the OSC target device and configuration for your set up.
3)Double click on the timer0 interrupt and choose the nearest frequency that's lower than desired frequency.
4) Determine optimum tmr0 value, and create your new flowchart using the new tmr0 value ,and place within a Cblock at the top of the interrupt macro as described in the main text above.

Edit Changed
20x10E6/4/2 = 125000 = 2.5MHz
to
20x10E6/4/2 = 2500000 = 2.5MHz

Thank you to achillis1 for spotting that error.
Attachments
Timer0 Value.fcf
(16 KiB) Downloaded 596 times
Martin

medelec35
Matrix Staff
Posts: 9520
Joined: Sat May 05, 2007 2:27 pm
Location: Northamptonshire, UK
Has thanked: 2585 times
Been thanked: 3815 times
Contact:

Re: Timer0 and obtaining desired interrupt frequency/delay.

Post by medelec35 »

Attached is an improved version. I have used four switches, rather than pot.
Two switches perform +10 and -10. the other two switches perform +1 and -1

Important thing to remember is Actual interrupt frequency is DOUBLE the indicated frequency.
Delay = 1/Frequency.

You will need to set up correct configuration settings for your target device.

Martin.
Attachments
Timer0 Value1.fcf
(11 KiB) Downloaded 545 times
Martin

Post Reply