Timers are common features of most microcontroller. In simplified terms a timer is just a register whose value keeps increasing (or decreasing) by a constant rate without the help of the CPU. The CPU can read or write this register any time. It reads it find out how much time has elapsed. The Timer register can have the following bit length

  • 8 bit timers - These can count between between 0-255
  • 16 bit timers - These can count between 0-65536
  • 32 bit timers - These can count between 0-4294967296

A timer has a clock source, for example of the clock source of 10KHz is input to a timer then one increment will take 100uS (micro second). This clock source can be obtained from the CPU clock. The CPU clock of popular MCU ranges from 1 MHz to 20Mhz, this can be sometimes too fast. To help us out their is a thing called prescaler in the MCU. The job of prescaler is to divide the CPU clock to obtain a smaller frequency. The PIC Micro that we will use in this example has the following prescaler division factors available.

  1. 256
  2. 128
  3. 64
  4. 32
  5. 16
  6. 8
  7. 4
  8. 2
  9. 1 (Prescaler by-passed)

Timers are also called Counters this is because they can be used to count external events. The following example illustrate the fact.

timer used as counter in pic

Counter Operation.

The above setup can be used to measure the RPM (speed in revolution per minute) of the rotating wheel. A small magnet is attached in the edge of the wheel. Whenever this magnet is exactly below the Magnetic sensor its output becomes high. This output is connected to the T0CKI pin of the MCU. The T0CKI stands for Timer0 Clock Input Pin. So each time the magnet passes by the sensor the timer register inside the MCU is incremented. You can note one this that all this happens without the help of CPU. CPU can do other task and read the Timer register only when required.

Overflow

An overflow occurs when a timer register has already counted the maximum value it can count. At overflow the counter value become 0 again. For example when an 8 bit timer has the value 255 and receive another clock that will set it to 0 and generate an overflow. An overflow can trigger an interrupt and the ISR can handle it.

Using TIMER0 of PIC18F4520

PIC18F4520 has four different timers. The simplest is the TIMER0 so we will learn how to use it first. In this example the TIMER0 is configured as follows.

  • 8 Bit Mode
  • Clock Source from Prescaler
  • Prescaler = FCPU/256 (Note: FCPU= Fosc/4)
  • Over flow INT enabled

Our FCPU=20MHz/4 (We are running from 20MHz XTAL)

=5MHz

Time Period = 0.2uS
Prescaler Period = 0.2 x 256 = 51.2uS (Prescaler is set to divide frequency by 256)
Overflow Period = 51.2 x 256 = 13107.2 uS (Each over flow takes 256 counts)
= 0.0131072 sec

So we need 1/0.0131072 Overflows to count for 1 sec
= 76.2939 Overflows

For that we maintain a counter to keep track of overflows.

When an over flow occurs the PIC jumps to ISR, where we increment the counter. And when counter becomes 76 we toggle RB1 pin. This pin is connected to LED. Therefore we have a LED which is ON for 1 sec and Off for 1sec.

Simple Program to Learn Operation of PIC TIMER0 in HI-TECH C and MPLAB


/*****************************************************************

A simple example to demonstrate the use of PIC Timers. In this 

example the TIMER0 is configured as follows.

*8 Bit Mode
*Clock Source from Prescaler
*Prescaler = FCPU/256 (Note: FCPU= Fosc/4)
*Over flow INT enabled

As our FCPU=20MHz/4 (We are running from 20MHz XTAL)
=5MHz

Time Period = 0.2uS
Prescaller Period = 0.2 x 256 = 51.2uS
Overflow Period   = 51.2 x 256 = 13107.2 uS
                  = 0.0131072 sec

So we need 1/0.0131072 Over Flows to count for 1 sec
= 76.2939 Overflows

So we keep a counter to keep track of overflows.

When an over flow occurs the PIC jumps to ISR where we
increment counter. And when counter becomes 76 we toggle
RB1 pin. This pin is connected to LED. Therefore we
have a LED which is ON for 1 sec and Off for 1sec.


Target Chip: PIC18F4520
Target Compiler: HI-TECH C For PIC18 (http://www.htsoft.com/)
Project: MPLAP Project File

Author: Avinash Gupta
Copyright (c) 2008-2010
eXtreme Electronics, India
www.eXtremeElectronics.co.in

                     NOTICE
                  -------------
NO PART OF THIS WORK CAN BE COPIED, DISTRIBUTED OR PUBLISHED WITHOUT A

WRITTEN PERMISSION FROM EXTREME ELECTRONICS INDIA. THE LIBRARY, NOR ANY PART
OF IT CAN BE USED IN COMMERCIAL APPLICATIONS. IT IS INTENDED TO BE USED FOR
HOBBY, LEARNING AND EDUCATIONAL PURPOSE ONLY. IF YOU WANT TO USE THEM IN 
COMMERCIAL APPLICATION PLEASE WRITE TO THE AUTHOR.

*****************************************************************/

#include <htc.h>


//Chip Settings
__CONFIG(1,0x0200);
__CONFIG(2,0X1E1F);
__CONFIG(3,0X8100);
__CONFIG(4,0X00C1);
__CONFIG(5,0XC00F);


unsigned char counter=0;//Overflow counter

void main()
{
   //Setup Timer0
   T0PS0=1; //Prescaler is divide by 256

   T0PS1=1;
   T0PS2=1;

   PSA=0;      //Timer Clock Source is from Prescaler

   T0CS=0;     //Prescaler gets clock from FCPU (5MHz)

   T08BIT=1;   //8 BIT MODE

   TMR0IE=1;   //Enable TIMER0 Interrupt
   PEIE=1;     //Enable Peripheral Interrupt

   GIE=1;      //Enable INTs globally

   TMR0ON=1;      //Now start the timer!

   //Set RB1 as output because we have LED on it

   TRISB&=0B11111101;

   while(1);   //Sit Idle Timer will do every thing!
}

//Main Interrupt Service Routine (ISR)
void interrupt ISR()
{
   //Check if it is TMR0 Overflow ISR

   if(TMR0IE && TMR0IF)
   {
      //TMR0 Overflow ISR
      counter++;  //Increment Over Flow Counter

      if(counter==76)
      {
         //Toggle RB1 (LED)

         if(RB1==0)
            RB1=1;
         else
            RB1=0;

         counter=0;  //Reset Counter

      }

      //Clear Flag
      TMR0IF=0;
   }
}

The program begins by Setting up TIMER0. The TIMER0 can be configured using a single register called T0CON which stands for TIMER0 control register. The details of each bit is given below.

Name TMR0ON T08BIT T0CS T0SE PSA PS2 PS1 PS0
Initial Value
1
1
1
1
1
1
1
1
BIT
7
6
5
4
3
2
1
0

BIT7 - TMR0ON: Timer0 On, set this to 1 to start the timer.

BIT6 - T08BIT: =1 for 8 bit mode and =0 for 16 bit mode.

BIT5 - T0CS: Timer0 clock source. =1 for T0CLK pin input i.e. counter mode. Set to 0 for internal instruction clock.

BIT4 - T0SE: Used in counter mode only. Please see datasheet for details.

BIT3 - PSA: Prescaler Assignment. Set this to 0 to assign prescaler or 1 to by pass it.

BIT2 to BIT0 - PS2 to PS0: Prescaler Division factor select

PS2 PS1 PS0  
0 0 0 Divide by 2
0 0 1 Divide by 4
0 1 0 Divide by 8
0 1 1 Divide by 16
1 0 0 Divide by 32
1 0 1 Divide by 64
1 1 0 Divide by 128
1 1 1 Divide by 256

So as per our requirement we have set the bits of T0CON register on program startup. This configures the TIMER0 as we require. Lets have a look at the code that initializes the TIMER0

//Setup Timer0
T0PS0=1; //Prescaler is divide by 256
T0PS1=1;
T0PS2=1;
PSA=0; //Timer Clock Source is from Prescaler
T0CS=0; //Prescaler gets clock from FCPU (5MHz)
T08BIT=1; //8 BIT MODE
TMR0IE=1; //Enable TIMER0 Interrupt
PEIE=1;   //Enable Peripheral Interrupt
GIE=1;    //Enable INTs globally
TMR0ON=1; //Now start the timer!
//Set RB1 as output because we have LED on it
TRISB&=0B11111101;
while(1); //Sit Idle Timer will do every thing!

As you can see in the above code, first we set up the bits of T0CON then we enable Timer Overflow interrupt, after that peripheral interrupt and finally enable interrupt globally. PEIE i.e. Peripheral Interrupt bit can enable or disable all peripheral interrupt. GIE or Global Interrupt bit is the master bit that can disable all interrupts.

Then when set PB1 i/o pins as output so that it can control a LED. The LED is connected to MCU by using series resistor to GND. Finally we enter an infinite loop that does nothing. As our timer is set up and running each times it overflows we increment counter by one. When counter becomes 76 we toggle the RB1 pin and reset the counter variable.

In HI-TECH C you can create an ISR (that is Interrupt service routine) by using the keyword interrupt. The ISR function can have any valid C function name. Its argument should be void and the return type should also be void. In our example we have named it "ISR".

void interrupt ISR()

Whenever TIMER0 overflow the CPU stops it current operation and jumps to the ISR. This is called interrupt(or exception) condition. As soon as it enters the ISR we check if it is the TIMER0 overflow interrupt by checking the TMR0IF (Timer0 interrupt flag). We also check if the interrupt is enabled (by checking TMR0IE i.e. Timer0 interrupt enable bit). If both the conditions are met we execute the TIMER0 Overflow ISR Code.

Schematic for Testing TIMER0 of PIC18F4520

pic18f4520 timer0 test schematic

Schematic For Testing TIMER0 of PIC18

The circuit is described in this article.

Running Demo On 40 PIN PIC Development Board

The PIC development board from eXtreme Electronics has all core circuit required in most PIC projects. So we can use it to easily test the above demo program. All you need to do is to short jumper J5, this will connect the LED to RB1 that's it!

PIC18 Sample Code Downloads

By
Avinash Gupta

May 13, 2010