Wednesday, September 29, 2010

PIC16F887/877 programming in C Tutorial 9 (Timers Interrupts)

Timers Interrupt:
Now lets see the interrupt of timers. As we know Timer0 will generate an interrupt when the TMR0 register overflows from FFh to 00h. The T0IF interrupt flag bit of the INTCON register is set every time the TMR0 register overflows, regardless of whether or not the Timer0 interrupt is enabled. The T0IF bit must be cleared in software. The Timer0 interrupt enable is the T0IE bit of the INTCON register. However we will use TMR0IF bit for interrupt programming.

The Timer1 register pair (TMR1H:TMR1L) increments to FFFFh and rolls over to 0000h. When Timer1 rolls over, the Timer1 interrupt flag bit of the PIR1 register is set. To enable the interrupt on rollover, you must set these bits:
• Timer1 interrupt enable bit of the PIE1 register
• PEIE bit of the INTCON register
• GIE bit of the INTCON register
The interrupt is cleared by clearing the TMR1IF bit in the Interrupt Service Routine.

For interrupt programming we have to create ISR (interrupt service routine); so that when an interrupt will occur ISR will take care of it. So, to use timers interrupt; first we have to enable the global interrupt by setting the GIE bit of intcon register, then the interrupts of the respective timer.

Code:  
unsigned cnt, cnt1, cnt2;

void interrupt() {
  if (TMR2IF_bit) {
    cnt2++;                    // increment counter
    TMR2IF_bit = 0;           // clear TMR2IF
    TMR2 = 0;
    if (cnt2 >= 122) {
      PORTc = ~PORTc;         // Toggle PORTc LEDs
      cnt2 = 0;                // Reset cnt
    }
   
  }
  if (TMR0IF_bit) {
    cnt++;                 // increment counter
    TMR0IF_bit = 0;        // clear TMR0IF
    TMR0   = 0;
    if (cnt >= 122) {         //1 sec delay
      PORTd = ~PORTd;      // Toggle PORTd LEDs
      cnt = 0;             // Reset cnt
    }
   
  }
  if(tmr1if_bit){
      tmr1if_bit=0;
      cnt1++;
      tmr1h=128;
      tmr1l=0;
      if(cnt1>=36){
           porta=!porta;
           cnt1=0;
        }
    }
 
 
}

void main() {
  OPTION_REG = 0x84;       // Assign prescaler to TMR0 32
 ////////////// commect for 877///////////////
  ansel=0;
  anselh=0;
  c1on_bit=0;
  c2on_bit=0;
///////////////////////////////////////
  TRISc = 0;               // PORTc is output
  PORTc = 0xFF;            // Initialize PORTc
  TRISd = 0;               // PORTd is output
  PORTd = 0xFF;            // Initialize PORTd
  TRISa = 0;               // PORTa is output
  PORTa = 1;            // Initialize PORTa
  TMR0  = 0;              // Timer0 initial value
  INTCON = 0xA0;           // Enable TMRO interrupt
  cnt = 0;                 // Initialize cnt

  t1con=1;
  tmr1if_bit=0;
  tmr1h=128;
  tmr1l=0;
  tmr1ie_bit=1;
  cnt1=0;
  intcon=192;
 
  cnt2 = 0;                    // initialize cnt
  PORTc = 0xFF;               // Initialize PORTc
  TRISc =   0;                // PORTc is output
  T2CON = 7;               // Timer2 settings
  TMR2  =   0;                // Initialize Timer2 register
  TMR2IE_bit = 1;             // enable interupt
  INTCON = 0xC0;              // Set GIE, PEIE

}

This code toggle the bits of port a, b and d when the interrupts of timer 1, 0, and 2 respectively. The time duration is about 0.5 sec, 1 sec, and 2 sec.

void interrupt() is the isr taking care of interrupts; handling interrupts and take decision according to them.

Schematic:

1 comment:

  1. Hello sir.
    i need code read ADC to show 7 segment 3-4 display with 16f877a
    mikroC programming sir.(DC voltage meter with 7 segments)

    ReplyDelete