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.

MSP430G2553: Timer Interrupt to debounce Button

Part Number: MSP430G2553

Tool/software:

Hi everyone,

I want to toggle my LED on the MSP-EXP430G2 Launchpad. I implemented a interrupt which gets activated, when I press the Button S2. In this interrupt I activate the Timer A0, in order to debounce the button.

Unfortunately, the debouncing does not work properly, because I can only jump into the Timer interrupt function, when the delay variable (count variable for the timer) is so small, that the debouncing doesn't work.

I do not get into the Timer Interrupt, when the Delay variable is too high. Do you have any suggestions what I am doing wrong here?

That is my code so far:

#include <msp430.h>

#define SW BIT3
#define GREEN BIT6
#define DEBOUNCE 20000

void main(void) {
    WDTCTL = WDTPW | WDTHOLD;           // Stop watchdog timer

    P1DIR |= GREEN;                     // Set LED pin -> Output
    P1OUT &= ~GREEN;

    P1DIR &= ~SW;                       // Set SW pin -> Input
    P1REN |= SW;                        // Enable Resistor for SW pin
    P1OUT |= SW;                        // Select Pull Up for SW pin

    P1IES |= SW;                       // Select Interrupt on Falling Edge
    P1IE |= SW;                         // Enable Interrupt on SW pin

    TA0CCR0 = DEBOUNCE;                 // Set delay time
    TA0CCTL0 = CCIE;                    // Enable Timer A0 interrupt in compare mode
    TA0CTL = TASSEL_2 | MC_0 | TACLR ;           // Clock & timer stopped

    __bis_SR_register(LPM4_bits + GIE); // Enter LPM4 and Enable CPU Interrupt
}

#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
    TA0CTL |= MC_1;                     // set Timer A0
    P1IFG &= ~SW;                       // Clear SW interrupt flag
}

#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A0_ISR(void)
{
    // Stop Timer A0
    TA0CTL &= ~MC_1;  // Stop mode

    // Check if the button is still pressed
    if (!(P1IN & SW))
    {
        // Toggle output pin (P1.2)
        P1OUT ^= GREEN;
    }

    // Clear Timer A0 interrupt flag
    TA0CTL &= ~TAIFG;
}

  • For button debounce I prefer a different method. A preiodic interrupt reads the switch inputs and stores this into a small array. Array size and timer period depending on your needs.

    To debounce, you either AND the bits together or use OR depending on which state you are looking for. You can also compare to the current state to detect edges only. An example of the interrupt code:

    /*
      Timer A interrupt does:
    
      1) Wakes up the main routine periodically.
      2) Tracks the state of the pushbuttons.
     */
    
    __attribute__ ((wakeup, interrupt(TIMERA0_VECTOR))) void Timer_A(void)
    {
      static int switch_index = 0;
      /*
        Read pushbutton switches.
       */
      switches[switch_index++] = P2IN;
      switch_index &= DEBOUNCE-1;
    
      if((++tick & (TIMER_A_RATE/MAIN_RATE-1)) == 0)
        {
          add_event(TICK);
        }
    }
    

  • Hey,

    thanks for your opinion. But can you explain to me, why my option isn't working properly?

    Thanks again.

  • SMCLK (TASSEL=2) is switched off in LPM4. As long as the switch keeps bouncing (Port_1() gets called repeatedly) SMCLK is started up for short periods, but once the bouncing finishes SMCLK is permanently off so TA0 doesn't tick.

    See if you get different results with LPM0.

**Attention** This is a public forum