We’ve used a GPIO configured as an output to turn a light on and off: we set the GPIO pin to output high voltage and the light turned on; we set the GPIO pin to output low voltage and the light turned off.
GPIOs can also be configured as inputs. When a GPIO is configured as an input the voltage on the GPIO pin is converted into a 0 (low voltage) or 1 (high voltage) and can be read in the appropriate GPIO configuration register. For the MSP430, the unfortunately named PAIN register reports the voltage value on each of the GPIO pins on Port 1. Why “PAIN”? Remember that the MSP430’s GPIO Port 1 and Port 2 are combined into Port A, and so PAIN is the “Port A INput register”. PAIN bit 0 corresponds to P1.0, bit 1 corresponds to P1.1, and so on.
Suggested puns: PAIN points, no PAIN no gain, and anything with the word “PAINful”.
The MSP430 F5529 LaunchPad dev kit that we’re using has a couple of buttons on it. Each of these buttons is tied to a GPIO. If the GPIO connected to a button is configured as an input, then that GPIO’s PAIN register bit will show if the button is pressed or not.
Let’s walk through an example where we’ll configure one of the LaunchPad’s button GPIOs as a input. If the button is pressed we’ll turn on the LED. If the button is not pressed we’ll turn off the LED.
Note: I’m not going to take the fastest route through this example! Instead I’m going to intentionally take a few wrong turns along the way. After making a wrong turn, I’ll stop, pull out the map, backtrack, and get back onto the right road. And then I’ll pick a better metaphor.
Why aren’t I just giving you the final answer? These are wrong turns that you’ll probably take at some point too!
Hopefully you can learn from the wrong turns and poorly chosen metaphors so that when you make a wrong turn in the future, you can find your way back to the right road using something you’ve learned here.
It’ll take at least a couple of posts to explain it all, so let’s get started.
I’ve chosen the button labeled as P1.1 on the LaunchPad. Here’s a picture of me pointing to it:
When button P1.1 is pressed, we’ll turn on the LED on P1.0 (the same light we’ve been playing with for the last few weeks). When button P1.1 is not pressed, we’ll turn off the LED on P1.0. We’ll use our Assembly Playground environment to do this example in assembly.
First we configure P1.0 as an output and P1.1 as an input (this pin is connected to the push button we want to monitor). The direction register (PADIR) sets each GPIO as an input or an output like this:
; Set GPIO P1.0 to be an output (PADIR bit 0 == 1) BIS.B #1, &PADIR_L ; Set GPIO P1.1 to be an input (PADIR bit 1 == 0) BIC.B #2, &PADIR_L
Before we get too far, let’s create a simple infinite loop that does nothing. We’ll use the Code Composer Studio debugger to run the infinite loop, push the P1.1 button, and verify that the corresponding value in the PAIN register changes.
Here’s the entire program:
; Set GPIO P1.0 to be an output (PADIR bit == 1) BIS.B #1, &PADIR_L ; Set GPIO P1.1 to be an input (PADIR bit == 0) BIC.B #2, &PADIR_L MainLoop: ; infinite loop that does nothing JMP MainLoop
Put this code into the assembly language playground we’ve built over the last few weeks, load it on your LaunchPad, and single step (Run->Step Over) until the code is inside the MainLoop infinite loop. Make sure you are not pressing the P1.1 button.
Open the Registers window and find the Port_A section: this shows us the GPIO configuration registers for Port_A, which controls our P1.1 button. It should look like this:
Here you can see the PAIN bit 1 is 0: this means the voltage on GPIO pin P1.1 is low. Now try pressing and holding the P1.1 button while single stepping to see PAIN1 (that’s the PAIN register’s bit 1) value while the button is pressed. You have to hold down the button while single stepping because the CCS debugger only updates the Registers view when code is running.
We expect to see PAIN1 change to ‘1’ when we are pressing and holding the button… but we don’t! PAIN1 is still 0, regardless if we’re pressing the button or not. If PAIN1 was 0 when not pressing the button, shouldn’t PAIN1 be 1 when pressing the button? What’s going on here?
I’ve intentionally skipped something to give you the experience of being confused by pin configurations. Because I care about you. Snarky joking aside, you will be confused by GPIO configurations when you work with a new board. When you are confused by unexpected results, it’s good to step back and ask yourself, “What am I missing? What are my assumptions? And which assumptions are wrong?”
We assumed that the button was connected to the P1.1 GPIO pin so that when the button is pressed the GPIO will be a high voltage, and when the button is not pressed the GPIO will be a low voltage.
Let’s check out that assumption by looking at the schematic. A schematic is a picture of what a circuit board looks like. It shows all the chips, connections, and other components that make up a circuit board. If you’re ever confused about something hardware-related, start with the schematic.
TI has squirreled away the schematic a few clicks away from the main MSP430 F5529 LaunchPad page. Schematics are sometimes listed under “design files,” which is how TI lists theirs. Click the “Download design files” red button on that page and you’ll be brought here: http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSP-EXP430F5529LP/latest/index_FDS.html
Then click on the “MSP-EXP430F5529LP Hardware Design Files” link which downloads a zip file. In that zip file look in the Hardware directory: you’ll find the schematic in a file called “MSP-EXP430F5529LP_Schematic.pdf”.
Take a look at that schematic. See if any of it makes sense. No worries if it doesn’t: I’ll pick up next week with the schematic, specifically how to use it to figure out how the button should work.
This post is part of a series. Check out the complete Embedded Software Engineering 101 series here.