Saturday, March 5, 2016

PIC16F84A Timer0 interrupt


PIC16F84A blink without delay
The microcontroller PIC16F84A has 1 timer which is timer0, this timer has a resolution of 8-bit and an interrupt-on-overflow from FFh to 00h. This topic shows how to use timer0 interrupt to blink an LED.
The timer0 interrupt is generated when the TMR0 register overflows from FFh to 00h.
To enable the timer0 interrupt GIE bit (INTCON<7>) must be 1 which can be done using the following CCS C command:
enable_interrupts(GLOBAL) ;
Also T0IE bit (INTCON<7>) must be 1 which can be done using the following command:
enable_interrupts(INT_TIMER0) ;
Bit T0IF (INTCON<2>) must be cleared in software by the Timer0 module Interrupt Service Routine before re-enabling this interrupt and this is done using the following command:
clear_interrupt(INT_TIMER0) ;
We can set the timer0 preload value (initial value) using the following command:
set_timer0(preload_value) ;
where preload_value is an unsigned 8-bit number.
The clock source can be internal or external through RA4/T0CKI pin.
Prescaler rate of the timer0 can be: 2, 4, 8, 16, 32, 64, 128 or 256. The clock source and prescaler can be set using the following CCS command:
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256) ;
To compute the timer0 frequency use the following equation:
Timer0_freq = MCU_freq / {4 * Prescaler * (256 - TMR0)} 
where TMR0 is timer0 preload value.
and: peroid = 1/Timer0_freq which is time to interrupt.
PIC16F84A Timer0 interrupt example circuit:
This is a simple example which uses timer0 interrupt to make an LED connected to RA0 blinking at a frequency about 1Hz.
pic16f84a timer0 interrupt ccs pic c
PIC16F84A Timer0 interrupt example CCS PIC C code:
The timer is used to interrupt every 50ms and to make the LED ON for 500ms and OFF for 500ms, the interrupt must be interrupted 10 times, that why a variable i is used.
HS oscillator used with frequency of 4MHz.
// PIC16F84A timer0 interrupt example
// Timer0 is interrupted every 49.92ms (approximately 50ms)
// Pin RA0 toggles its status every 10 * 49.92ms (approximately 500ms)
// http://ccspicc.blogspot.com/
// electronnote@gmail.com

#include <16F84A.h>
#fuses HS,NOWDT,PUT,NOPROTECT
#use delay(crystal=4000000)

byte i ;
#INT_TIMER0
void timer0_isr(void)
{
  clear_interrupt(INT_TIMER0);    // Clear timer0 interrupt flag bit
  set_timer0(61);
  i++;
  if(i > 9)
  {
    i = 0;
    output_toggle(PIN_A0);
  }
}

void main()
{
  // Setup timer0 with internal clock and 256 prescaler
  setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
  set_timer0(61);                // Timer0 preload value
  clear_interrupt(INT_TIMER0);   // Clear timer0 interrupt flag bit
  enable_interrupts(INT_TIMER0); // Enable timer0 interrupt
  enable_interrupts(GLOBAL);     // Enable all unmasked interrupt
  output_low(PIN_A0);

  while(TRUE) ;              // Endless loop
}