This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

switch button Interrupt



Hello,

    My aim is if I press a push button P1.3 then LED (P1.0) should off/on otherwise LED (P1.6) should blink. 

In Below code, LED (P1.0) is on/off when i press button and LED (P1.6) glows once.   LED (P1.6) glows once and wait for the user to press the button. My task is  the the code should blink the LED (P1.6) continuously if user doesn't press the button. If the user press the button then LED (P1.0) should glow and then LED (P1.6) should blink until user press the push button. Please tell me how can i do this. 

#include <msp430g2553.h> 

#define LED0 BIT0
#define LED1 BIT6 
#define BUTTON BIT3



int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
P1DIR |= (LED0 + LED1); // Set P1.0 to output direction 
// P1.3 must stay at input
P1OUT &= ~(LED0 + LED1); // set P1.0 to 0 (LED OFF)
P1IE |= BUTTON; // P1.3 interrupt enabled

P1IFG &= ~BUTTON; // P1.3 IFG cleared

__enable_interrupt(); // enable all interrupts
while(1)
{
     P1OUT ^= LED1;

__bis_SR_register(LPM4_bits + GIE);

}
}

#pragma vector=PORT1_VECTOR
__interrupt void PORT1_ISR(void)
{

P1OUT ^= BIT0;
P1IFG = 0; // clear interrupt
__bic_SR_register_on_exit(LPM4_bits);
}

Thanks.

  • First when you say blink there needs to be some kind of timing involved, just toggling P1OUT will not do much. 

    http://processors.wiki.ti.com/index.php/MSP430_LaunchPad_LED_Timer this may be a good starting point. 

  • david haye said:
    while(1)
    {
         P1OUT ^= LED1;

    __bis_SR_register(LPM4_bits + GIE);

    }
    
    

    Hi David,

    What you do here is that saying to processor to toggle LED1.6 and go to sleep. Since it's sleeping it does not toggle the LED unless you press the button and wake it up in the ISR. So removing low power mode command will solve your problem.

    Regards,

    Gunay

  • Hi Gunay,

    Will you please explain me little bit more.  

    Thanks.

  • Hİ David,

    The line __bis_SR_register(LPM4_bits + GIE) makes CPU to go Low Power Mode, where CPU sleeps and waits for an interrupt to start working again. Therefore when you write it in your while loop, the execution first toggles your LED once, than go to LPM. When the chip is in LPM it stops executing the program, i.e. while loop pauses until an interrupt occurs (That is pressing the button in your case). When you press the button this part of the code starts working:

    #pragma vector=PORT1_VECTOR
    __interrupt void PORT1_ISR(void)
    {

    P1OUT ^= BIT0;
    P1IFG = 0; // clear interrupt
    __bic_SR_register_on_exit(LPM4_bits);
    }

    This toggles your LED1.0, than makes CPU to go out from LPM by the line __bic_SR_register_on_exit(LPM4_bits);

    After interrupt execution finished, code goes to main, where it is interrupted, i.e. into the while loop. Since the CPU is awake it toggles the LED once more and goes to sleep again. This process is repeated everytime you pressed the button. So if you want to LED1.6 to toggle continuously you shold remove the LPM lines and put some time delay in your while loop. To do that you can use __delay_cycles(); function.

    Does that help? Feel free to ask if I missed a point to be cleared.

    Regards,

    Gunay

  • Hi Gunay,

         Thank you very much for the explanation. I understood the concept of interrupt.

    In my task, the code should not wait for the user to press the button. In below code, the instructions 1-3 should run continuously. If user presses button, then it should execute instruction 4-5 and then after interrupt, the code starts from instruction1. 

    I am writing a code for digital clock with date. My aim is to enter date and time manually, and then code should run and display date and time on LCD.

    First the code tells the user on the LCD to enter the date(1-31). the user has to press the button to set the date. if the user doesnt press the button for 3-4 seconds, then automatically the code should jump to month(1-12) and so on...

    Instructions 1-3 are to wait for 3 seconds if button is not pressed in between and jump to next target..  Instruction4-5 is to increment date or month or etc..

    
    
    
    
    #include <msp430g2553.h> 
    
    #define LED0 BIT0
    #define LED1 BIT6 
    #define BUTTON BIT3
    
    
    
    int main(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
    P1DIR |= (LED0 + LED1); // Set P1.0 to output direction 
    // P1.3 must stay at input
    P1OUT &= ~(LED0 + LED1); // set P1.0 to 0 (LED OFF)
    P1IE |= BUTTON; // P1.3 interrupt enabled
    
    P1IFG &= ~BUTTON; // P1.3 IFG cleared
    
    __enable_interrupt(); // enable all interrupts
    while(1)
    {
       instruction1;
       instruction2;
       instruction3;

    __bis_SR_register(LPM4_bits + GIE);

    }
    }

    #pragma vector=PORT1_VECTOR
    __interrupt void PORT1_ISR(void)
    {

      instruction4;

      instruction5;
    P1IFG = 0; // clear interrupt
    __bic_SR_register_on_exit(LPM4_bits);
    }

  • Hi David,

    To be able to do what you explained, you must know about timers, and use them. If you understood interrupts, I recommend you to read user's manual timer_a section parallel with the example codes provided by TI. 

    User's manual: http://www.ti.com/lit/ug/slau144j/slau144j.pdf

    Code examples for G2xx3 series: http://www.ti.com/general/docs/lit/getliterature.tsp?baseLiteratureNumber=slac485&fileType=zip

    Also take a look at http://processors.wiki.ti.com/index.php/MSP430_LaunchPad_(MSP-EXP430G2)

    Spend some time on theese and understand how modules of the chip work, and try to imitate sample projects an modify them, it will give you better understanding. Then you can start digital clock knowing what are you doing.

    Regards,

    Gunay

  • David, there are multiple approaches how you could implement this. Which one to use depends on what the application shall do (in future) besides this.

    You can implement a state machine. You can count while loops or use a timer for the timeout, you can use LPMs and be awaken by timer or port pin ISR or count down a variable in the timer ISR and set it in the port pin ISR.

    Hoever, in any case you'll nee dsome debouncing for the pin. Either in hardware or in software.

    btw: the __enable_interrupts() intrinsic is identical to adding the GIE bit to the LPM entry. Both set the GIE bit in the status register and allow interrupts globally. However, in the first case, you probably don't want interrupts to happen at this point.

    Also, you should check whether putting instruciton 4+5 into the iSR is really necessary. If it is a simple assignment, then it is okay, but if it requires some time-consuming or even blocking task (like sending a new information to a display), it shouldn't be done inside an ISR. ISRs should be fast-in and fast-out.

**Attention** This is a public forum