Timer0 and it's Programming

Timer0 Module

The Timer0 module incorporates the following features:

  • Software selectable operation as a timer or counter in both 8-bit or 16-bit modes
  • Readable and writable registers
  • Dedicated 8-bit, software programmable prescaler
  • Selectable clock source (internal or external)
  • Edge select for external clock
  • Interrupt-on-overflow

The T0CON register controls all aspects of the module‚Äôs operation, including the prescale selection. It is both readable and writable. A simplified block diagram of the Timer0 module in 8-bit mode is shown in Figure. Figure shows a simplified block diagram of the Timer0 module in 16-bit mode.


7TMR0ON: Timer0 On/Off Control bit
  • 1 = Enables Timer0
  • 0 = Stops Timer0 
6T08BIT: Timer0 8-Bit/16-Bit Control bit
  • 1 = Timer0 is configured as an 8-bit timer/counter
  • 0 = Timer0 is configured as a 16-bit timer/counter 
5T0CS: Timer0 Clock Source Select bit
  • 1 = Transition on T0CKI pin
  • 0 = Internal instruction cycle clock (CLKO) 
4T0SE: Timer0 Source Edge Select bit
  • 1 = Increment on high-to-low transition on T0CKI pin
  • 0 = Increment on low-to-high transition on T0CKI pin 
3PSA: Timer0 Prescaler Assignment bit
  • 1 = TImer0 prescaler is not assigned. Timer0 clock input bypasses prescaler.
  • 0 = Timer0 prescaler is assigned. Timer0 clock input comes from prescaler output
2R/W: Read/Write Information bit Used in I2C mode only. 
1-0T0PS<2:0>: Timer0 Prescaler Select bits
  • 111 = 1:256 Prescale value
  • 110 = 1:128 Prescale value
  • 101 = 1:64   Prescale value
  • 100 = 1:32   Prescale value
  • 011 = 1:16   Prescale value
  • 010 = 1:8     Prescale value
  • 001 = 1:4     Prescale value
  • 000 = 1:2     Prescale value

Timer0(8-bit mode) Block Diagram

timer0 8bit mode


Timer0 can operate as either a timer or a counter; the mode is selected with the T0CS bit (T0CON<5>). In Timer mode (T0CS = 0), the module increments on every clock by default unless a different prescaler value is selected.

If the TMR0 register is written to, the increment is inhibited for the following two instruction cycles. The user can work around this by writing an adjusted value to the TMR0 register. The Counter mode is selected by setting the T0CS bit (= 1). In this mode, Timer0 increments either on every rising or falling edge of pin RA4/T0CKI. The incrementing edge is determined by the Timer0 Source Edge Select bit, T0SE (T0CON<4>); clearing this bit selects the rising edge. Restrictions on the external clock input are discussed below. An external clock source can be used to drive Timer0; however, it must meet certain requirements to ensure that the external clock can be synchronized with the internal phase clock (TOSC). There is a delay between synchronization and the onset of incrementing the timer/counter.

Timer0 (16-bit mode) Block Diagram

timer0 16 bit mode


TMR0H is not the actual high byte of Timer0 in 16-bit mode; it is actually a buffered version of the real high byte of Timer0 which is not directly readable nor writable (refer to Figure 11-2). TMR0H is updated with the contents of the high byte of Timer0 during a read of TMR0L. This provides the ability to read all 16 bits of Timer0 without having to verify that the read of the high and low byte were valid, due to a rollover between successive reads of the high and low byte. Similarly, a write to the high byte of Timer0 must also take place through the TMR0H Buffer register. The high byte is updated with the contents of TMR0H when a write occurs to TMR0L. This allows all 16 bits of Timer0 to be updated at once.


An 8-bit counter is available as a prescaler for the Timer0 module. The prescaler is not directly readable or writable; its value is set by the PSA and T0PS<2:0> bits (T0CON<3:0>) which determine the prescaler assignment and prescale ratio. Clearing the PSA bit assigns the prescaler to the Timer0 module. When it is assigned, prescale values from 1:2 through 1:256 in power-of-2 increments are selectable. When assigned to the Timer0 module, all instructions writing to the TMR0 register (e.g., CLRF TMR0, MOVWF TMR0, BSF TMR0, etc.) clear the prescaler count.

Timer0 Interrupt

The TMR0 interrupt is generated when the TMR0 register overflows from FFh to 00h in 8-bit mode, or from FFFFh to 0000h in 16-bit mode. This overflow sets the TMR0IF flag bit. The interrupt can be masked by clearing the TMR0IE bit (INTCON<5>). Before reenabling the interrupt, the TMR0IF bit must be cleared in software by the Interrupt Service Routine. Since Timer0 is shut down in Sleep mode, the TMR0 interrupt cannot awaken the processor from Sleep.

Timer0 Programming

Write a C18 Program to toggle only portb.4 bit continuosly every 50 milliseconds, using Timer0, 16-bit mode, Prescaler=4 ,XTAL=10Mhz
Solution -

  • Timer0, 16-bit mode
  • Prescaler = 4
  • XTAL i.e. fosc = 10 MHz
  • PORTB.4 bit to be toggled every 50 millisec.

Delay Generation Calculations - 4 Marks

 Crystal Freq = 10 MHz

Internally Timer Module divides this Crystal frequency by the factor of 4 to generate 1 machine cycle frequency ,
Therefor 1 machine cycle frequency = Crystal frequeny / 4
                                                          =10 MHz / 4
                                                          = 2.5 MHz
Here Prescaler of 1:4 is given so this machine cycle frequency is again gets divided by 4
                                                          =2.5 MHz / 4
                                                          = 0.625 MHz
 Hence T = 1 / 0.625 MHz = 1.6 microSeconds

i.e. 1 machine cycle generates delay of = 1.6 microSeconds

 As we have to generate  delay  of 50 milliSeconds and we are using Timer0 in 16-bit mode i.e. 16-bit Timer,
Hence it can count maximum machine cycles of 65535 + 1 machine cycle of overflow =65536
Therefor Number of Machine cycles required to generate delay of 50 milliSeconds are = 31250 Machine cycles

Initial Value to be loaded in Timer Registers = ( Final Value + 1 )- number of Machine cycles required
                                                                     = (65535 +1) - 31250
                                                                     = 34286 decimal
                                                                     = 85EE Hexadecimal
Hence Value to be loaded in TMR0L= EE H, TMR0H= 85 H

#include <p18f4520.h>
#pragma config OSC=HS
#pragma config PWRT=OFF
#pragma config WDT=OFF
#pragma config DEBUG=ON, LVP=OFF
void main (void);
void Timerdelay();
void main ()
TRISBbits.RB4 = 0x00;   //Direction of RB4 as an output
PORTB=0X10;    // RB4 as HIGH
Timerdelay();  // Call Delay routine using Timer
PORTB=0X00;   //RB4 as LOW
Timerdelay(); // Call Delay routine using Timer
void Timerdelay()
T0CON = 0x01;              //set up timer0 - 16-bit mode, 1:4 prescaler
TMR0H = 0X85;         //Load initial value in TMR0H
TMR0L = 0XEE;      //Load initial value in TMR0L
INTCON0bits.TMR0IF=0;    //Clear TMR0IF flag initially
T0CONbits.TMR0ON = 1;    // Start Timer0
while(INTCON0bits.TMR0IF==0) ///monitor TMR0 interrupt flag
T0CONbits.TMR0ON=0;         // Stop Timer0
INTCON0bits.TMR0IF=0;      //Clear TMR0IF flag


  • Created, Edited and Notes by Prof. Sujit Wagh, SKNCOE, Pune
  • WikiNote Foundation

Last modified: Tuesday, 17 September 2019, 12:39 PM