The TI Tiva Launchpad boards are an excellent way to get started working with ARM microcontrollers. With the Tivaware software suite, they’re not too much harder than an Arduino to program, either. I’ve found the tutorials from TI and elsewhere online to be very helpful. Unfortunately, the TI tutorials go over GPIO outputs, which are pretty simple, but they totally skip inputs! For someone totally unsure where to look for the correct documentation, I feel this is a major oversight. Fortunately, I’ve been able to figure it out with the help of some 3rd party tutorials. Here’s my take on how to use GPIO inputs, with references back to the TI material so you can get an idea of where to look for functionality in the main documentation.

I’ll explain the setup and put the code at the end of this post, along with some links.

Setup

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
int main(void)
{
  SysCtlClockSet(SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);	// set up the clock
  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);	// enable port F
  GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);	// enable outputs on the launchpad LED pins

As usual, we need to include the appropriate headers for the board and set up the clock. We also need to enable port F. Then, we set up GPIO F1, F2 and F3 as outputs. This is where the LaunchPad’s red, green and blue LEDs are connected. Also note that some pins need to be unlocked with a code from the datasheet before you can use them. That’s because they’re normally used for one of the programming interfaces. There are examples of this in the Tiva tutorials from TI. Take a look at my tutorial on how to unlock GPIOs.

GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_4);	// make F4 an input

GPIOPadConfigSet(GPIO_PORTF_BASE,GPIO_PIN_4,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);	// enable F4's pullup, the drive strength won't affect the input

Here’s where we start getting to the input side of things. We need to enable port F4 as an input. Pretty simple, but it doesn’t end there. To make it work correctly, we’ll configure the pin to have an internal pullup resistor. WPU stands for ‘weak pullup resistor’ - you could change this to WPD for a pulldown. The details of this function can be found on page 264 here.

By giving the pin an internal pullup, we know that when the button is pressed, the input will be grounded (from the LaunchPad datasheet). Otherwise, it’ll be pulled up to 3.3v. That’s the key to making inputs work, but let’s peek at the rest of the code.

Loop

while(1)
  {
    uint32_t pinVal=0;	// variable to hold the pinRead
    pinVal= GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4);	// read F4

Pretty standard microcontroller stuff, we’ve got a while(1) loop. This will run forever. Next, we create a 32-bit integer to take the value of GPIOPinRead. This function returns a 32 bit value, but we only need bits 1-8, which will be set if any of the pins on the port are high. GPIOPinRead takes the base port and the specific pin as arguments.

If

if( (pinVal & GPIO_PIN_4)==0){	// AND to strip out anything but the value read from F4
      GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 2);	// turn on one LED
    }
    
    else{
      GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 4);	// turn on a different LED
    }

Next we have an if statement. It’s pretty easy to see what’s being done here. If the pin is high, we turn on GPIO F2 (that’s the else condition). Otherwise, our input is low (button pressed) and we’ll turn on pin F1.

There’s a little bit going on in the if statement though. We’re taking the value from GPIOPinRead, which will have a 0 or a 1 in the position of any pins we read. We logical AND it with the GPIOPIN4 variable, which will strip away anything except the value in Pin 4’s position. If pin 4 was high, we will get a result of 1. If pin 4 was low, we get a 0. This is because we AND the value on the input, in the input’s place, with a 1 in the input’s place.

What’s the delay for?

//   SysCtlDelay(7000000); // uncomment me if you need debouncing

  }
}

There is an optional delay at the bottom of the code. This is for very simple debouncing of the button. Essentially, when you push a button, it doesn’t immediately connect one way or the other. It’ll actually bounce around between connected and disconnected. This is a physical phenomenon due to springiness. It’s very fast, but not too fast for a micro to keep up with. In some applications, like if you were making each button press increment a counter, you would likely see more than one increment of the counter for each button press, due to the button bouncing a little bit. If you’re just using a button to turn on an LED with no latching, button bounce isn’t something to worry about.

Button bounce

By waiting around for a few ms after reading the button, we physically give it time to settle into wherever it wants to be. Debouncing could be a whole series of blog posts, as you can deal with it in multiple ways through hardware or software. If you find you need it, busy wait delays are the most simple way to deal with it, though they’re definitely not the best.

bounce waveform Button bounce waveform

Complete code

Here’s the complete code for this tutorial. It’s all commented and should be easy to figure out. The project containing this code was actually the Lab 2 code from TI’s set of tutorials. The includes and build options are the same, you just need to put in a few lines to enable and work with the inputs.

/* 
Tivaware input tutorial
*/

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
int main(void)
{
  SysCtlClockSet(SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);	// set up the clock
  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);	// enable port F
  GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);	// enable outputs on the launchpad LED pins
  GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_4);	// make F4 an input

  GPIOPadConfigSet(GPIO_PORTF_BASE,GPIO_PIN_4,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);	// enable F4's pullup, the drive strength won't affect the input
  while(1)
  {
    uint32_t pinVal=0;	// variable to hold the pinRead
    pinVal= GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4);	// read F4
    
    if( (pinVal & GPIO_PIN_4)==0){	// AND to strip out anything but the value read from F4
      GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 2);	// turn on one LED
    }
    
    else{
      GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 4);	// turn on a different LED
    }
        
    //   SysCtlDelay(7000000); // uncomment me if you need debouncing

  }
}

Resources

I’ll end off with some resources for learning about the ARM LaunchPad. There will definitely be more tutorials from me as well!

TI LaunchPad resources

Tivaware Reference

TI LaunchPad Workshop

AllaboutEE Input Tutorial (C++)

Luis Electronic Projects Input Tutorial