Amateur Rocketry. The Timer0 Module

The Timer0 is one of the three built-in timers inside a PIC18 microcontroller. According to the Datasheet, 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

For this project we will use the module as a timer in 16-bit mode. That will allow us to get a specified sample rate of 10 or 20 Hz, depending on what the conversion speeds of the sensors allow us.

The Timer0 has several registers to it which control all aspects associated to its operation (see Datasheet for default values and more information):

NameBit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0
TMR0LTimer0 Register, Low Byte
TMR0HTimer0 Register, High Byte

INTCON: Contains various enable, priority and flag bits,

  • GIE: Global interrupt enable(1)/disable(0) bit
  • PEIE: Peripheral interrupt enable(1)/disable(0) bit
  • TMR0IE: TMR0 overflow interrupt enable(1)/disable(0) bit
  • TMR0IF: TMR0 overflow interrupt flag bit

T0CON: This is the Timer0 Control Register,

  • TMR0ON: Timer0 on(1)/off(0) control bit
  • T08BIT: Timer0 8-bit(1)/16-bit(0) control bit
  • T0CS: Timer0 counter(1)/timer(0) select bit
  • T0SE: Timer0 source high-to-low(1)/low-to-high(0) edge select bit
  • PSA: Timer0 prescaler assignment bit, off(1)/on(0)
  • T0PS2..T0PS1: Timer0 prescaler select bits

Now, lets say that we want get samples at 10 Hz. The value of Timer0 will then be defined by

\displaystyle \mathrm{TMR0} = 65536 - \frac{T_{\mathrm{int}}F_{\mathrm{osc}}}{4\cdot 2^{n+1}}

If we have the microcontroller running at 4 MHz (Fosc) and we want to gather samples at 10 Hz (1/Tint), knowing that the prescaler is defined in the form 1:2n+1 with n from 0 to 7. Iterating in the equation above, we need a prescaler with n = 0 (T0PS = 0b000) so that TMR0 > 0, which yields a value of 15536 = 0x3CB0,


Following, we can see a snippet of how the code would look like:


void High_Int_Handler (void);

#pragma code High_Int = 0x08 // high priority interrupt vector
void High_Int(void) {
_asm goto High_Int_Handler _endasm

#pragma interrupt High_Int_Handler
void High_Int_Handler (void) {
if (INTCONbits.TMR0IF) {
INTCONbits.TMR0IF = 0; // set Timer0 flag back to '0'
TMR0H = 0x3C;
TMR0L = 0xB0;


void main(void) {
// Initializations

INTCONbits.GIE = 1; // global interrupt enable
INTCONbits.TMR0IE = 1; // TMR0 overflow interrupt enable

// Timer0 configuration
T0CON = 0x80; // Timer0 on, 16-bit, timer mode, prescaler on, n = 1
TMR0H = 0x3C;
TMR0L = 0xB0;

while (1);