In another article we have seen, in a very simple way, how to set the registers to be used by the tmr0 to generate and interrupt (Link). An important aspect of this timer is the right setting of the prescaler. Interrupts generated by timers are an important peculiarity of any microcontroller and are widely used in any application where the time is an important matter.
At first we have to say what a prescaler represents: it is a simple frequency divider. The tmr0 is an 8 bits timer that increases its value every 4 (fosc/4) clock pulses and generates an interrupt immediately after it overflows the value of 255. Usually this speed must be considered too fast and cannot be used directly otherwise the picmicro will slow too much.
![]() |
Where clock = Fosc/4 and prescaler set to 1/8 If the clock of the microcontroller is 4mhz and the prescaler is set to 1/8, the prescaler will set the tmr0 to a clock of 125Khz. |
Sometimes, for a human being, to deal with a clock of 125Khz is really useless. We are used to think in seconds, minutes, hours therefore we have to find a way to calculate the conversion between a pic-minded clock and a human mind time.
Sometimes this calculation is not easy, as we know the period is the inverse of the frequency, therefore 125khz = 1/125000 = 8uS. In this case, therefore, will be generated an interrupt on overflow every 8*256uS = 2,048mS ... for a human this is a nonsense and almost useless during the programming procedure of a microcontroller because, usually, we have to deal with the time units our mind is used to: milliseconds, seconds, minutes, hours etc.
![]() |
![]() |
The question is: how to obtain an interrupt every an exact interval time of time?
At first we have to consider that we can vary the pulse needed to get an overflow of the timer. We have said before that tmr0 is a counter 0-255 that will generate an overflow (and therefore an interrupt) when it value exceed 255 starting again to count from 0. To change this behaviour we can precharge the variable tmr0 with a value making the count shorter. If for instance we assign the value 50(dec) to tmr0 every time we get an overflow the count will start from that value.
At this point we can say that there are two solutions to calculate all values regarding the prescaler and the tmr0 precharging value: the first is the use of a picmicro tmr0 calculator :-) http://eng-serve.com/pic/pic_timer.html where we can immediately calculate the values for our needs, or we can manually calculate these values according to the following formula:
freq = (fosc/4) / (256-tmr0value) * Prescaler
in this case, if we desire to obtain an overflow every 1ms using a crystal of 4mhz with a prescaler of 1/4 the tmr0 offset value should be 6.
In any case before to leave the routine interrupt() we have to remember to
- reset the tmr0 to the offset value;
- reenable the interrupt (INTE=1)
- clear the flag (INTF = 0)
Tmr0 and the prescaler
In another article we have seen, in a very simple way, how to set the registers to be used by the tmr0 to generate and interrupt (Link). An important aspect of this timer is the right setting of the prescaler. Interrupts generated by timers are an important peculiarity of any microcontroller and are widely used in any application where the time is an important matter.
At first we have to say what a prescaler represents: it is a simple frequency divider. The tmr0 is an 8 bits timer that increases its value every 4 (fosc/4) clock pulses and generates an interrupt immediately after it overflows the value of 255. Usually this speed must be considered too fast and cannot be used directly otherwise the picmicro will slow too much.
![]() |
Where clock = Fosc/4 and prescaler set to 1/8 If the clock of the microcontroller is 4mhz and the prescaler is set to 1/8, the prescaler will set the tmr0 to a clock of 125Khz. |
For a human being sometimes to deal with a clock of 125Khz is really useless. We are used to think in seconds, minutes, hours therefore we have to find a way to calculate the conversion between a pic-minded clock and a human mind time.
Sometimes this calculation is not easy, as we know the period is the inverse of the frequency, therefore 125khz = 1/125000 = 8uS. In this case, therefore, will be generated an interrupt on overflow every 8*256uS = 2,048mS ... for a human this is a nonsense and almost useless during the programming procedure of a microcontroller because, usually, we have to deal with the time units our mind is used to: milliseconds, seconds, minutes, hours etc.
![]() |
![]() |
The question is: how to obtain an interrupt every an exact interval time of time?
At first we have to consider that we can vary the pulse needed to get an overflow of the timer. We have said before that tmr0 is a counter 0-255 that will generate an overflow (and therefore an interrupt) when it value exceed 255 starting again to count from 0. To change this behaviour we can precharge the variable tmr0 with a value making the count shorter. If for instance we assign the value 50(dec) to tmr0 every time we get an overflow the count will start from that value.
At this point we can say that there are two solutions to calculate all values regarding the prescaler and the tmr0 precharging value: the first is the use of a picmicro tmr0 calculator :-) http://eng-serve.com/pic/pic_timer.html where we can immediately calculate the values for our needs, or we can manually calculate these values according to the following formula:
freq = (fosc/4) / (256-tmr0value) * Prescaler
in this case, if we desire to obtain an overflow every 1ms using a crystal of 4mhz with a prescaler of 1/4 the tmr0 offset value should be 6.
In any case before to leave the routine interrupt() we have to remember to:
- reset the tmr0 to the offset value;
- reenable the interrupt (INTE=1)
- clear the flag (INTF = 0)
void interrupt()
{
if (INTCON.INTF ==1) // timer 0 interrupt flag
{
PORTB.F0 = ~PORTB.F0; // reverts portb bit0
INTCON.INTF = 0; // clear the flag
INTCON.INTE = 1; // reenable the interrupt
TMR0 = 6; // reset the timer preset count
}
}
void main()
{
TRISB = 0x00;
PORTB = 0;
OPTION_REG.T0CS = 0; // Tmr0 clock source internal
OPTION_REG.T0SE = 0; // TMR0 Edge Select
OPTION_REG.PSA = 0; // Prescaler to Timer0
OPTION_REG.PS2 = 0; // Prescaler to 1/4
OPTION_REG.PS1 = 0;
OPTION_REG.PS0 = 1;
TMR0 = 6; // offset value for the timer register
INTCON = 0; // clear the interrupt control register
INTCON.INTE = 1; // Enables the TMR0 interrupt
INTCON.INTF = 0; // bit2 clear timer 0 interrupt flag
INTCON.GIE = 1; // bit7 global interrupt enable
do
{
} while(1) ;
}
In many other cases the use of the internal timers of a picmicro is the perfect solution to solve many problems connected with a periodical activity; unfortunately for many other applications the internal timers (we'll see later the 16bit tmr1 and tmr2 timers) are not a valid solution.
To generate really precise timings for a digital clock, for instance, better to consider the use of an external clock generator like the Dallas DS1307, or equivalent, real time clock.