cpicc89mikroc

Timer based interrupt in PIC microcontroller using mikroC for PIC


I am facing a problem while implementing a timer based interrupt in mikroC for PIC.

I want to toggle a port pin for 8 times if there is a keypress at PORTC.F0 and there should be a delay of say 100ms between the toggles.

Normally this would be very easy using a delay function

for (i=0;i<=8;i++)
 {
  PORTB.F0=~PORTB.F0;
  Delay_ms(100);
 } 

But during the period, any other keypresses are missed by the system. So I thought of implementing the solution using interrupts.

#define SW PORTC.F0

char ttime,i;
volatile flag;

void Inittimer()
{
 T1CON         = 0x01;
 TMR1IF_bit    = 0;
 TMR1H         = 0x06;
 TMR1L         = 0x00;
 TMR1IE_bit    = 1;
 INTCON        = 0xC0;
}

void Interrupt()
{
 if (TMR1IF_bit)
 {
  TMR1IF_bit    = 0;
  TMR1H         = 0x06;
  TMR1L         = 0x00;
  ttime--;
  if (ttime==0)
  {
   flag=1;
  }
 }
}

void main()
{
 Inittimer1();
 TRISB    = 0;
 TRISC.F0 = 1;
 PORTB    = 0x00;
 while(1)
 {
 if (SW==0)
 {
  ttime=3;
 }
  if (flag==1)
  {
   for (i=0;i<=8;i++)
   {
    PORTB=~PORTB;
    flag=0;
   }
  }
 }
}

Nothing is working. Can somebody please help me to correct the code?


Solution

  • When you initialize your timer:

    void Inittimer()
    {
     T1CON         = 0x01;
     TMR1IF_bit    = 0;
     TMR1H         = 0x06;  // No prescaler? I doubt your clock speed is 40-some KHz!
     TMR1L         = 0x00;
     TMR1IE_bit    = 1;
     INTCON        = 0xC0;
    }
    

    Why don't you control the LED directly from the ISR ?

      if (ttime)
          PORTB.F0 = (--ttime & 1);  // ttime is not decremented when led is not blinking.
      else
          PORTB.F0 = 0;              // ensures the LED is off.
    

    To start blinking 8 times:

    if (SW==0)
    {
      PORTB.F0 = 1;
      ttime = 16;
    }
    

    Note that with a 100ms clock interrupt, the first 'blink' of the LED may last up to 200ms... This is why many like to work with a faster timer interrupt (this has usually other uses as well), controlling the led would require adding a soft post-scaler

       if (blinking)
       {
          if (--blinkTimer == 0)
          {
             blinkTimer = BLINK_DELAY;      // whatever number it takes for 100ms.
             PORTB.F0 = (--blinking & 1);  
          }
       }
       else
       {
           PORTB.F0 = 0
       }
    

    To start blinking:

    if (SW==0)
    {
      blinking = (2 * BLINKS) - 1;
      blinkTimer = BLINK_DELAY;
      PORTB.F0 = 1;
    }
    

    This should get you a more even first blink.