PIC interrupt delay_ms

interruptspic

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);
    }
}

Best Answer

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.