Electronic – MSP430 Launchpad buttons do not behave properly and cannot see variables

cembeddedmicrocontrollermsp430texas instruments

I just got an MSP430F5529 Launchpad and have done one tutorial where i make the LED located at P1.0 blink. I am using code composer studio as my IDE

Now i am trying to get the LED at P1.0 (red) and the one at P4.7 (green) to alternate depending on if the button located at P2.1 is pressed down.

No matter what I do the button doesn't seem to change anything. What's even more odd is that pressing the button changes multiple bits on P2IN instead of just P2.1.

I have tried using the button at P1.1 (actually i tried that first), and i got similar behavior where the button changes multiple bits and sometimes changes none at all. But the worst part is that even if the bits change and it compares the bit of input to what it should be for pressed, it never registers as pressed.

Also i cannot see my variables so i added a 'blah' variable and tried to set it to 0x00 to force myself into the loop, but it doesnt do anything!!!! It's like it just deletes the blah variable.

Here is the code i am trying to get working:

#include <msp430f5529.h>

//defines
#define red_LED   BIT0 //red LED @ P1.0
#define grn_LED   BIT7 //green LED @ P4.7
#define BTN       BIT1 //button is located a P2.1
#define BTN_PRESSED      0x00

//prototypes
void delay(int n);

//main
void main(void) {
    WDTCTL = WDTPW + WDTHOLD; //disable watchdog timer

    unsigned int flash; //variable to store LED flash flag

    P1OUT = 0; //set output as low
    P1DIR |= red_LED;  // set LED pins to outputs

    P4OUT = 0; //set output low
    P4DIR |= grn_LED; //set green LED as output

    /* Setting up Switch */
    P2OUT = 0;                                   //set output as low
    P2DIR &= ~BTN;                               // Set the switch pin to input
    P2REN |= BTN;                                // Use an internal resistor
    P2OUT |= BTN;                                // The internal resistor is pullup

    for (;;) {//inf loop

        for (flash=0; flash<7; flash++) {
            P1OUT |= red_LED;    // red LED on
            delay(60000);             // call delay function
            P1OUT &= ~red_LED;   // red LED off
            delay(60000);             // delay again
        }

        while ((P2IN & BTN) == BTN);  // wait for button press, loop forever while P1IN is high (button unpressed)

        for (flash=0; flash<7; flash++) {
            P4OUT |= grn_LED;    // green LED on
            delay(60000);            // call delay function
            P4OUT &= ~grn_LED;   // green LED off
            delay(60000);            // delay again
        }

        while ((P1IN & BTN) == BTN);  // wait for button press, loop forever while P1IN is high (button unpressed)

    }//end inf loop
} // main


//functions
void delay(int n) {
    //delays for a count of 60000 ticks
    unsigned int count;
    for (count=0; count<n; count++);
} // delay

and here is the test code i am trying to debug to no avail (the button works if i get into the delay() loop, but i can never get into it!

#include <msp430f5529.h>

//defines
#define red_LED   BIT0
#define grn_LED   BIT7
#define BTN       BIT1
#define BTN_PRESSED      0x00

//prototypes
void delay(int n);

//main
void main(void) {
    WDTCTL = WDTPW + WDTHOLD; //disable watchdog timer

    unsigned int flash; //variable to store LED flash flag

    P1OUT = 0; //set output as low
    P1DIR |= red_LED;  // set LED pins to outputs

    P4OUT = 0; //set output low
    P4DIR |= grn_LED; //set green LED as output

    /* Setting up Switch */
    P2OUT = 0;                                   //set output as low
    P2DIR &= ~BTN;                               // Set the switch pin to input
    P2REN |= BTN;                                // Use an internal resistor
    P2OUT |= BTN;                                // The internal resistor is pullup

    int blah = 0;

    for(;;){
        if((blah) == BTN_PRESSED){
            delay(5);             // call delay function
        }
    }

//functions
void delay(int n) {
    //delays for a count of 60000 ticks
    unsigned int count;
    for (count=0; count<n; count++);
} // delay

I must be doing something fundamentally wrong because blah never appears in my debuggers variable list and the delay(5) never runs!

Best Answer

The compiler sees that the delay() loop is empty, so it cleverly concludes that the function can compute the same result much faster by omitting the loop altogether.

The blah variable has the same problem: the compiler sees that its value never gets changed inside the program, so it is effectively a constant, and does not need to be actually stored anywhere. (And the if((blah) == BTN_PRESSED) can never happen, so it can be omitted.)

To tell the compiler that it should actually access some variable, you have to declare that variable as volatile:

volatile int blah = 0;        // allows changes with the debugger
...
volatile unsigned int count;  // force the compiler to actually count up, even
                              // if the compiler does not see any effect

Please note that all registers like P2IN are declared as volatile because they could change without an assignment seen by the compiler.

Please also note that the compiler does not know that interrupt handlers can interrupt other functions, so it might not bother to re-read some variable that might have been changed by the interrupt. So variables that are shared between some interrupt handler and the main program must also be declared volatile.


By default, all GPIO pins are configured as inputs. These inputs are implemented with MOSFETs, and their gate is so small that it can pick up a random charge from any nearby signals, or even through the air, if you don't actively drive an input high or low. This is called a "floating input".

Even worse, an input that happens to be half charged switches both the "1" and the "0" connections half on, and there will flow a current from the power supply to ground.

The User's Guide says in section 12.2.8:

Configuring Unused Port Pins

Unused I/O pins should be configured as I/O function, output direction, and left unconnected on the PC board, to prevent a floating input and reduce power consumption. The value of the PxOUT bit is don't care, because the pin is unconnected. Alternatively, the integrated pullup/pulldown resistor can be enabled by setting the PxREN bit of the unused pin to prevent the floating input.