In the previous article, I explained the significance of Timers in microcontrollers and how you can use timers in 8051. In this article, I will be covering how you can initialize and use Timers in PIC16F877A microcontroller. Just as in 8051, the role of timers in PIC and any other microcontroller is exactly the same. The difference lies in the size of timers, the number of timers and their respective registers that are associated with them.

There are 3 Timers in PIC16F877A, with timer0 and timer2 as 8-bit timers and timer1 as a 16-bit timer. Before getting into these timers, it is important to understand the concept of Prescalar and Postscaler in a microcontroller.



A prescalar, in general, is a circuit which takes clock pulses as input and provides an output at a much lower rate. For example, suppose I have a prescalar which is set with a prescale rate of 1:4. What it means is when the prescalar is fed with 4 clock pulses at its input, It will provide a single pulse at its output. Thus, using prescalar you can make your timer count at a much lower rate and achieve long delays.

A postscalar delays the frequency with which an interrupt occurs. It decides the number of times the timer has to overflow before the occurrence of the timer interrupt. If the postscale rate is set to 1:4, then the timer has to overflow 4 times before the interrupt occurs.



Timer 0

It is an 8-bit timer which can also be configured to work as a counter. It uses a user programmable Prescalar which is shared with the watchdog timer. The register associated with Timer0 is the option_reg, TMR0 register, and INTCON register. TMR0 register holds the value to be incremented just like in 8051, where you have TH1-TL1 and TH0-TL0. The programmer must write into this register which will then be incremented till FFh.



R͞B͞P͞U: (Internal pull-up bit)
On setting this bit to 0, weak pull-ups for all the bits in PORTB are activated. Weak pull-ups are disabled when set to 1.

INTEDG: (Interrupt Edge Select bit for RB0/INT pin)
An interrupt will be generated on a rising edge when set. When cleared, interrupt will be generated on a falling edge.

The first 2 bits are not associated with timer/counter operation.

PSA: (Prescalar assignment bit)
This bit needs to be set for enabling Prescalar. Disabled when set to 0.

PS2: PS1: PS0: (Prescale rate select bit)

T0CS: (Timer0 clock source select bit)
This bit when set will count the pulses on T0CLK(RA4) pin of PIC16F877A. When set to 0, It will count internal clock cycles(Fosc/4 when no prescalar is used).

T0SE: (TMR0 source edge select bit)
When set, Timer/counter will increment on a high to low transition on T0CLK pin. When cleared, Timer/counter will increment on a low to high transition on T0CLK pin.


INTCON register
  • If you intend to use timer interrupt, you’ll need to set the first two bits i.e GIE and PEIE which are global and peripheral interrupt enable bit.
  • TMR0IE is the timer interrupt enable bit. This bit needs to be set for enabling timer 0 interrupt.
  • TMR0IF is the timer0 overflow flag bit. It will be set to 1 when timer0 overflows. If TMR0IE is set, the processor will jump to execute its ISR.



Timer 1

Timer 1 is a 16-bit timer. Two separate 8-bit registers are used to load values, TMR1H and TMR1L. Timer 1, therefore, can count up to FFFFH(65535). Just like in timer0, Timer 1 also uses prescalar and can work as a timer or a counter. The registers associated with timer1 are TMR1H-TMR1L, T1CON, PIR1, PIE1.

T1CON(Timer 1 control register)

T1CKPS1: T1CKPS0(Timer1 prescalar bits)
These two bits decide the prescale rate in timer1. Maximum achievable prescale rate using timer 1 is 1:8

T1OSCEN and T1S͞͞Y͞N͞C bits:

  • An internal crystal oscillator circuitry is built in for timer1 in PIC16F877A which requires an external crystal to operate, preferably a 32Khz crystal. This circuitry can be enabled by setting the T1OSCEN bit.
  • T1S͞͞Y͞N͞C bit come into picture when timer1 is being used in counter mode. When T1S͞͞Y͞N͞C bit is cleared, It synchronizes external clock pulses with the internal phase clock.
  • The above is only possible when the microcontroller is not in sleep mode because the internal oscillator is shut down in sleep mode and in such condition, Timer registers won’t increment but the prescalar will.
  • When T1S͞͞Y͞N͞C is set, synchronization is disabled.

TMR1CS: (Timer1 Clock Source Select bit)
When set, Timer1 counts external clock pulses on RC0(when T1OSCEN is 0) and RC1(when T1OSCEN is set). Counts internal clock pulse(Fosc/4) when cleared.

TMR1ON: (Timer 1 On bit)
Starts the timer when set. Stops when cleared.


PIR1 Register

Timer 1 overflow bit is contained in the PIR1 register(bit 0 of the PIR1 register). It is set when the timer rolls over FFFFh. It must be cleared by the programmer in the program itself.


PIE1 Register

Timer 1 overflow interrupt bit is contained in the PIE1 register(bit 0 of the PIE1 register). On setting it to 1, Interrupt is enabled. Cleared to disable timer1 overflow interrupt.



Timer 2

Timer2 is an 8-bit timer which uses TMR2 register to load values into. Timer2 uses a prescaler as well as a postscalar. Since it is an 8-bit timer it can count up to FFH. Timer2 module also uses a separate 8-bit register called Period register(PR register). This register is readable as well as writeable, i.e. the user can write 8-bit values in it. When timer2 is initiated, it starts incrementing TMR2 register. When the value in TMR2 matches with the value written in PR register, the timer rolls over and the overflow flag is set. By default, PR resister is loaded with FFh. The other registers associated with timer 2 are T2CON, PIR1, and PIE1.

T2CON(Timer 2 control register)

TOUTPS3: TOUTPS2: TOUTPS1: TOUTPS0 (Postscalar rate select bits)
These 4 bits are used to select the postscalar rate.

TMR2ON: (Timer 2 On bit)
When set, Timer2 begins incrementing; Stops when cleared.

T2CKPS1: T2CKPS2  (Timer2 prescale bits)
0:0 Prescale rate is 1:1
0:1 Prescale rate is 1:4
1:0/1 Prescale rate is 1:16


PIR1 and PIE1 register

Just like in timer1, the overflow flag bit and interrupt enable bit are located in PIR1 and PIE1 register respectively( Second last bit of both the registers i.e. TMR2IF and TMR2IE). Overflow is set when timer overflows and must be cleared by the programmer. Interrupt occurs on overflow when interrupt enable bit is set.

  • The formula for delay calculation:
    x is the value which you need to load in your timer register. The maximum delay will be achieved when x is 0 and prescale rate is set to its highest ratio. For timer 1 which is of 16-bit, the value 255 will be replaced by 65535.


Electronics engineer graduated from M.H. Saboo Siddik college of engineering. Currently working as Jr. Innovative engineer. Skilled in 8051, PIC and ARM microcontrollers. Circuit analyzation and Debugging. Constantly looking to acquire more skills which would help myself to become more proficient in embedded domain. Founder and blogger at LinkedIn profile:


Sam Farai Phiri · January 8, 2020 at 10:37 pm

I am confused on writing a program that generates a square wave of 200us on a pic16f877 using timer 2 overflow interrupt.
Please help

    Moiz · January 11, 2020 at 9:34 pm

    What is your Fosc value?
    Assuming you’re using a 16Mhz crystal. You need to set the prescale rate to 1:4 and load value 0xC8 in your PR2 register. The timer 2 will increment from 00h and reset to zero when it matches the value in PR2.

    eg: 200uS = (4*(255-x)*4)/16Mhz
    x = 55
    PR2 = 255-55
    Value to be loaded in PR2 = 200 (0xC8)

Leave a Reply

Your email address will not be published. Required fields are marked *