We've gotten to the point now where we can program the MSP430 and make it respond by flashing an LED or two. While being able to change pins to outputs is useful, it's the combination of input and output that make the microcontroller so powerful. The pushbutton is one of the simplest types of inputs, and will be very helpful for learning more about the peripherals.
There are all kinds of switches available on the market, and there are some differences in the ways they need to be attached to the MSP430. For now we'll look at single-pole, single-throw (SPST) types, such as the momentary push-button. The LaunchPad platform includes two of these types of buttons; one is connected to P1.3 (that's the button on the lower left of the board) and the other to the RST/SBWTDIO pin (pin 16 on the DIP).
If you are following the tutorial using the LaunchPad, then open up a copy of the LaunchPad User's Guide and turn to page 15 to see a circuit schematic of the target section of the board. You can see here that the two buttons are connected between their respective pins and ground. Note also that the same pins have 47 kΩ resistors connecting them to Vcc. To use pushbuttons in digital logic, they need to be able to provide a 1 in one state and a 0 in the other. When the button is up, the resistor ties the pins to Vcc, pulling up the voltage to whatever level the board is powered at (in the case of the LaunchPad, it's 3.6V). When you press the button, it closes the short to ground. So unpressed is logic 1, and depressed is logic 0.
You can use the opposite convention as well, reversing the positions of the button and the resistor. For obvious reasons, we call the first configuration a "pull-up resistor" and the second a "pull-down resistor". Without these resistors, the input pin would be floating, and could take on any value between ground and Vcc, which gives inconsistent behavior for your design. Whichever case makes more sense for your design, always remember to use the resistors to pull the open state up or down. A larger resistor (such as the 47 kΩ used on the LaunchPad) keeps the current draw from the button low. Ideally we only want to change the potential on the input pin and not use any power to do so.
You might recall that there are internal resistors on each of the GPIO pins for the MSP430 that can act as pull-up and pull-down resistors. The resistance value quoted for these in the MSP430 datasheets is large enough that the current draw would not be too high, but as readers have pointed out it may not be the best practice to use these for your push-buttons, especially while prototyping and testing.
With the resistors in place, using buttons in an MSP430 design is quite simple. Let's illustrate them by writing a program that flashes the red LED on P1.0 a few times, then flashes the green LED on P1.6 a few times after the button is pressed. Pressing the button again should return to the red LED, and so on. For this program, we'll need to configure the two LED pins as outputs and be sure the button pin (P1.3) is configured as an input. We'll use the technique from the Blinky program to take care of the LED delay again, so we'll need a counter as well. A second counter will keep track of the number of times the LED flashes.
The new thing needed is an ability to tell the MSP430 to check the state of the button periodically; we call this polling. When the program reaches the point where it is waiting for the user to push the button, it should check and recheck the button until it sees that it has been pressed. We can do this by using a logic operation to check the value on P1IN. Since the button is attached to P1.3, bit 3 of P1IN tells us if the button is pressed (logic 0) or unpressed (logic 1). The other bits of P1IN could, in principle, be anything, so how can we extract just the value of bit 3? A simple way is to use the & operator-- since x & 0 = 0 and x & 1 = x, then P1IN & BIT3 (0b00001000) will return 0b0000x000, where x is the current value of bit 3 in P1IN. Note that the result is not either 0 or 1, but rather 0 or 0b00001000, which is also the value BIT3. Since 0 corresponds to the pressed state, we can poll P1IN in a loop that continues while (P1IN & BIT3) == BIT3, or equivalently while (P1IN & BIT3) != 0.
I've written my own version of a program that uses this in pushy_G2211.c. Try coding the program up yourself first, and then compare it to mine. A couple of new techniques used in the code are the #define command in the header, and encapsulation of a re-used command in a function call. If you're not familiar with either of these techniques, brush up on them in your favorite, reliable book on C programming. Essentially, #define lets me rename the value BIT0 to something more descriptive-- in this case, red_LED. Since this doesn't change the value of BIT0, it can still be used in the code, or you can even define two things to be BIT0, as you would if you had LEDs on P1.0 and P2.0 of a larger MSP430 device. The delay() function also makes the code more readable, and illustrates the power of encapsulation. Since a delay function is so common, I could put this into a library, and then recall it whenever I want without having to retype the same thing over and over. I encourage you to use these and any other good coding practices as much as possible to help make your code easier to understand and reuse!
This code isn't perfect, as it can't account for all situations. What happens if you press the button while an LED is flashing? Since the input value only matters during the while loop, nothing. If you have ninja reflexes and push the button in a way where the MSP430 polls it before and after the pressing, then it never sees the button press. And what happens if you just hold the button down? The solution here is to use interrupts, which is a topic beyond this tutorial. But for now, you have a rudimentary way to use buttons.
Reader Exercise 1: Copy the code into a new CCS project and try loading Pushy into your G2211. Step through the code with the debugger to be sure it works. (Change the limit on count to save clicks. Change the limit on flash too, if you're not feeling particularly patient.) Note that to get the debugger to work with the button you need to be holding it down as you step into the next line. Try watching the P1IN register as you step through to see the input value change.
Reader Exercise 2: We didn't discuss the RST button on the LaunchPad; try letting the red LED blink, then push this button instead of the button on P1.3. (You'll have to terminate the debugger to get this to work.) What does it do? While the LaunchPad is configured in a way where this is the only function this button can have, it's a very useful tool to have, especially if you ever need to restart you program!