Electronic – MSP430 Prevent Bouncing

cdebouncemicrocontrollermsp430

I'm currently working on a homework that does: the first press to the button at P1.1 opens the LED at P1.0, the second press to the same button blinks the LED and the third press closes the LED.

I wrote a code for that in Code Composer Studio but the microcontroller does not work properly. It does the opening, blinking, and closing operations but when the LED starts to blink, I have to press the button a few times to close the LED. I think that causes from bouncing (What I mean by bouncing is in the picture below) or the for loop that I wrote for blink operation.
1

I added a for loop (for (i=10000; i>0; i--)) to prevent that but that didn't work.

Here is my code:


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

    P1DIR |= 0x01;              // Configuring P1.0 as output
    P1DIR &= 0xFD;              // Configuring P1.1 as input

    P1REN |= 0x02;              // Enable resistor for P1.1
    P1OUT |= 0x02;              // Setting the resistor as Pull-Up and P1.0 as low
    P1OUT &= 0xFE;
    
    volatile unsigned int i;
    int j = 0;

    while(1) {

        for (i=10000; i>0; i--);                // Delay loop to avoid bouncing
        if ( (~P1IN & 0x02) && j==0 ) {         // Check if the button is pressed and j is 0 for validating it's the 1st press
            P1OUT ^= 0x01;                      // If the button is pressed, then toggle P1.0 (LED is ON)
            j = 1;                              // Change the value of "j" to "1"
        }

        for (i=10000; i>0; i--);                // Delay loop to avoid bouncing
        if ( (~P1IN & 0x02) && j==1) {          // Check if the button is pressed and j is 1 for validating it's the 2nd press
            while(1) {                          // Infinite loop to run the code below until break (3rd press)
                P1OUT ^= 0x01;                  // Toggle P1.0 (LED is blinking)
                for (i=45000; i>0; i--);        // Wait before closing or opening the LED
                if (~P1IN & 0x02) {             // If the button is pressed for the 3rd time, then break the loop
                    break;
                }
            }
            j = 2;                              // If the loop is broken, then change the value of "j" to "2"
        }

        for (i=10000; i>0; i--);                // Delay loop to avoid bouncing
        if ( (~P1IN & 0x02) && j==2) {          // Checking if the button is pressed and j is 2 for validating it's the 3rd press
            P1OUT ^= 0x01;                      // If the button is pressed, then toggle P1.0 (LED is OFF)
            j = 0;                              // Change the value of "j" to "0" for returning to the beginng of the main loop (1st press)
        }
    }
}

How can I fix this issue? My code covers all the thing that we learn until now. So I shouldn't use any codes, variables etc. apart from my code. Thanks in advance!

Best Answer

You have to use the delay after spotting the first flank, not at some random location in the code. The most crude version would be this (pseudo code):

uint8_t pin=0;
uint8_t prev=0;

while(1)
{
  pin = PORTX;
  if(pin != prev) // edge detected
    break;
  prev = pin;
}

busy_delay();  // some 5 to 20 ms usually
pin = PORTX;  // read when the switch is done bouncing
// now you can use the value of pin

The more professional version involves a circular interrupt which reads the port at even time intervals and compares with previous read and stores the result if it's the same.