0
\$\begingroup\$

I'm using MikroC Pro, PIC16F1824 with XTAL 4Mhz.

Basically I have 2 mode of LEDs. I use serial cable to send which mode to play.

  • Mode 1 = On for 3 seconds and Off for 3 seconds.
  • Mode 2 = On for 1 seconds and Off for 1 seconds.

Everything works fine and I use an interrupt. But when I send a new mode to play, it waits until the current running mode is completed. It doesn't stop the current Mode immediately.

Questions:

  • How do I use interrupt to stop the current mode immediately (delay_ms) and play the new mode?
  • I was told I need to use counter looping. How does it work?

Code:

 void OnLed(short nMode){
if (nMode == 1)
{
    PWM1_Set_Duty(100);
    delay_ms(3000);
    PWM1_Set_Duty(0);
    delay_ms(3000);
}
else
{
    PWM1_Set_Duty(100);
    delay_ms(1000);
    PWM1_Set_Duty(0);
    delay_ms(1000);
} 
}
void interrupt()
{
    cnt++ ;             // Interrupt causes cnt to be incremented by 1
    PIR1.TMR1IF = 0;    // Reset bit TMR1IF
    TMR1H = 0xFC;       // TMR1H and TMR1L timer registers are returnesd
    TMR1L = 0x18;       // their initial values
}

`void main()
{

...

T1CON = 1;          // Turn on timer TMR1
PIR1.TMR1IF = 0;    // Reset the TMR1IF bit
TMR1H = 0xFC;       // TMR1H and TMR1L timer registers are returned
TMR1L = 0x18;       // their initial values
PIE1.TMR1IE = 1;    // Enable an interrupt on overflow
INTCON = 0xC0;      // Enable interrupt (bits GIE and PEIE)

...

UART1_Init(9600);

...

while(1)
{
    if (UART1_Data_Ready())
      {
        sByte = UART1_Read();
        if (sByte = '1')
            OnLed(1);
        else 
            OnLed(2);
    }
}
\$\endgroup\$
1
  • 3
    \$\begingroup\$ Someone marked this as off topic but this is a programming heavy question that is definitely related to the physical realities of a microcontroller. I would be interested in others thoughts. \$\endgroup\$
    – Kortuk
    Commented Jun 23, 2011 at 2:13

3 Answers 3

2
\$\begingroup\$

Instead of using delay_ms() to do your LED timing, you should use the timer interrupt for that. I don't know MikroC at all, but make sure you have the timing interrupts correct first. Then, figure out the duration between two successive timer interrupts. Using this value you can then add a global (static) variable to hold your upper bound for your counter (I guess in your case, cnt). You would calculate these two upper bound values manually: one for mode one, one for mode two (i.e. your counter should count up and reset back to 0 once it reaches the respective value). These values will determine your 3 sec or 1 sec delay. You could have another global variable to determine whether the LED should be on or off but you could do without it.

Now in the main code, you just need to change your counter bounds inside your if-else statement.

\$\endgroup\$
1
\$\begingroup\$

Sample of manual code

Interrupt calibrated to one second{
   timeCount++;
}

main{
  mode = readState;
  if mode = 1{
    if timeCount >= 1{
      LEDSTATE = !LEDSTATE;
      timeCont = 0
    }
  }
  if mode = 2{
    if timeCount >= 3{
      LEDSTATE = !LEDSTATE;
      timeCont = 0
    }
  }

}
\$\endgroup\$
0
\$\begingroup\$

I suspect what someone was suggesting is to move your OnLed() logic to the else condition in your loop in main(). Use the incrementing count to track the time to make the logic change. You can reset the change time easily on receiving a character.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.