This web site uses cookies. By continuing to browse the site you are agreeing to our use of cookies. Find out more.

Interrupt with TMR0 and prescaler

Last update: 31/07/2015

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.

Picmicro prescaler

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.

 

prescaler registro picmicro prescaler

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.

prescaler

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.

option_reg prescaler

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.  

Diritti riservati Cuteminds.com 2008-2015. Tutti i marchi riportati sono detenuti dai legittimi proprietari. Tutto il materiale e` liberamente utilizzabile ma non per scopi commerciali. Non si assume alcuna responsabilita` sul materiale pubblicato per eventuali danni diretti o indiretti che possano derivare dall`utilizzo di schemi, progetti o altro materiale presente nel sito. Inviare una mail a: remove-admin@cuteminds.com (contenuti) remove-webmaster@cuteminds.com (webserver) per domande e/o suggerimenti.