-1

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?

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
Ace
  • 11
  • 4
  • 2
    "Nothing is working" is not a problem description. _What_ isn't working? – Lundin Jun 26 '17 at 10:46
  • In hindsight, Nothing is working is indeed a very vague comment. I am trying to implement a PORT toggle every 100ms for exactly 8 times using timer interrupt. I tried working many options, none of them worked for me. The closest I came was to get the PORT toggled after a certain time delay using interrupt. But cannot stop it from toggling after n number of times. – Ace Jun 26 '17 at 11:58

2 Answers2

1

Well this doesn't look right:

  if (flag==1)
  {
   for (i=0;i<=8;i++)
   {
    PORTB=~PORTB;
    flag=0;
   }
  }

When you first see that flag is set, you immediately loop and toggle the output 8 times, without waiting for flag to turn back to 1. That's not right, it's overly simplified.

You need to look for the flag, then toggle the output and clear the flag, and wait for it to to get set again, maintaining the counter in parallel. The for loop is not the proper structure for this, since it will "lock out" the rest of the program and might cause keypresses to be missed.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • I did try doing what you suggested...instead of the for loop, I incremented another variable i after the port was toggled and the flag was cleared. I did put a conditional statement of `if (i>=8) {PORTB=0x00; i=0;}`This did not work. Basically, I can start the PORT to toggle after certain delay but cannot understand how to stop it from toggling after n number of cycles. – Ace Jun 26 '17 at 11:55
0

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.

Michaël Roy
  • 6,338
  • 1
  • 15
  • 19
  • Thanks for the help Michael. I did solve the problem, can you please check if the approach is correct? `while(i<8) { if (flag==1){ i++; PORTB.F0 = ~PORTB.F0; cnt=0;flag=0; } }` This does toggle the port pin 8 times and setting the value of cnt allows be to precisely set thedelay with which the port pin is toggled. Is this approach correct? – Ace Jun 29 '17 at 06:06
  • It is correct, but it blocks your main loop. What of all the other operations you may need to do? – Michaël Roy Jun 29 '17 at 21:22