HomeTM4C123G TutorialsTM4C123 GPIO Tutorial – Digital Input and Output using Tiva C LaunchPad

TM4C123 GPIO Tutorial – How to Use Digital Input and Output with Tiva C LaunchPad

The TM4C123 Tiva C LaunchPad is one of the best boards to start learning ARM Cortex-M programming. In this tutorial, we will learn how to use GPIO (General Purpose Input/Output) pins on the TM4C123 to control LEDs and read button inputs.

GPIO is the foundation of every embedded system. It allows the microcontroller to interact with the real world — turning LEDs ON or OFF, reading switches, or controlling sensors.
Before diving into advanced topics like UART, ADC, or PWM, it’s essential to understand how GPIO works.

We’ll use STM32CubeIDE with the TM4C123 microcontroller, and you’ll learn step by step how to:

  • Configure GPIO pins as input or output
  • Toggle LEDs using software
  • Read button states and control LEDs accordingly

By the end of this tutorial, you’ll be comfortable with basic digital I/O operations on the Tiva C LaunchPad, and ready to move toward interrupts and timers.

How to Use Digital Input and Output with Tiva C LaunchPad

Recommended Resources:

I have already covered how to create a project in CCStduio and configure system clock in the previous tutorials. This tutorial is going to be a continuation in this series, so you must read the following tutorials first:

Introduction to GPIO on TM4C123

What is GPIO in TM4C123?

GPIO stands for General Purpose Input/Output.
In the TM4C123 Tiva C microcontroller, GPIO pins are the basic interface between the microcontroller and the outside world. These pins can be configured as input or output, allowing the microcontroller to either read signals from sensors, switches, and buttons, or send signals to devices such as LEDs, motors, and relays.

The TM4C123 microcontroller comes with six GPIO portsPort A to Port F — providing a total of 43 GPIO pins. Each port is 8 bits wide, meaning it can handle up to 8 pins, although some ports may have fewer usable pins depending on the device package.

These GPIO pins are highly flexible. You can:

  • Configure each pin as digital input or output.
  • Enable internal pull-up or pull-down resistors.
  • Use alternate functions like UART, SPI, I2C, or PWM when needed.
  • Control output levels directly from software using registers.

GPIO is the first step in understanding how the TM4C123 communicates with other hardware components. It lays the foundation for working with all other peripherals in the system.


Why Learn GPIO Before Other Peripherals?

Before learning complex peripherals like UART, ADC, or timers, it’s important to master GPIO programming. Here’s why:

  1. Fundamental for All Embedded Applications
    GPIO operations form the base of every embedded project. Whether you’re blinking an LED, reading a button, or controlling a sensor, you’ll always use GPIO at some point.
  2. Simple and Easy to Understand
    Working with GPIO helps you get familiar with register-level programming, bit masking, and hardware-level control — concepts that are essential when dealing with any microcontroller peripheral.
  3. Visual Feedback for Learning
    Turning LEDs ON and OFF or reacting to a button press gives immediate feedback. This makes it much easier to debug your setup and understand how your code interacts with hardware.
  4. Gateway to Advanced Features
    Once you’re comfortable with GPIO, you’ll naturally be ready to explore interrupts, timers, and communication interfaces. All of these use similar concepts of configuration and control.

Understanding GPIO Ports and Pins on TM4C123

GPIO Port Names and Pin Count

The TM4C123 microcontroller includes multiple GPIO ports labeled from Port A to Port F. Each port typically contains 8 pins, named Px0 to Px7, where “x” represents the port letter.

However, not all pins are always available for general use — some are reserved for special functions like JTAG, NMI, or oscillator inputs. The exact number of usable GPIO pins depends on the specific TM4C123 variant and its package type.

Here’s a quick summary of the available GPIO ports on TM4C123:

PortPin RangeNotes
Port APA0 – PA7Commonly used for UART and SPI functions
Port BPB0 – PB7Supports I2C and PWM functions
Port CPC0 – PC7Some pins are reserved for JTAG
Port DPD0 – PD7Can be used for USB or GPIO functions
Port EPE0 – PE5Fewer pins, often used for ADC inputs
Port FPF0 – PF4Connected to onboard LEDs and switches

Each port must have its clock enabled through the SYSCTL_RCGCGPIO register before you can use it. Once the clock is active, you can configure individual pins as input or output, and control their logic levels directly through GPIO registers.


How GPIO Pins are Connected to the Tiva C LaunchPad LEDs and Buttons

The Tiva C LaunchPad (TM4C123GXL) provides easy access to GPIO pins through headers and onboard components like LEDs and switches.

Here’s how the onboard peripherals are connected:

ComponentGPIO PinPortFunction
Red LEDPF1Port FDigital Output
Blue LEDPF2Port FDigital Output
Green LEDPF3Port FDigital Output
Switch 1 (SW1)PF4Port FDigital Input (Active Low)
Switch 2 (SW2)PF0Port FDigital Input (Active Low)

When you press a switch, it connects the pin to ground (logic LOW). Therefore, the default state of the switches is logic HIGH due to internal pull-up resistors.

This simple configuration makes it easy to test GPIO programming — you can toggle LEDs or read button presses without any external components.


Unlocking and Configuring Special GPIO Pins (like PF0)

Some GPIO pins on the TM4C123 are locked by default for safety and debugging purposes. One common example is PF0, which is used as a Non-Maskable Interrupt (NMI) pin.

To use PF0 as a normal GPIO pin, you need to unlock it in software before configuration. This is done using a specific sequence involving the GPIOLOCK and GPIOCR registers.

Here’s how to unlock PF0:

  1. Write the unlock key 0x4C4F434B to the LOCK register of Port F.
  2. Set the corresponding bit for PF0 in the COMMIT (CR) register to allow changes.
  3. Once unlocked, configure PF0 as an input or output pin using normal GPIO functions.

Example:

HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = 0x4C4F434B;   // Unlock Port F
HWREG(GPIO_PORTF_BASE + GPIO_O_CR) |= 0x01;          // Allow changes to PF0

Once unlocked, you can set PF0 as input or output like any other GPIO pin.
This step is especially important when using the onboard SW2 button, since it’s connected to PF0.

By understanding which pins are locked, shared, or reserved, you can avoid conflicts and make full use of the TM4C123’s GPIO capabilities.

Setting Up GPIO in Code Composer Studio (CCS) for TM4C123

Before we start controlling LEDs or reading button inputs, we first need to set up GPIO in Code Composer Studio (CCS).
This section will guide you through creating a new project, adding the TivaWare library, and writing the basic code to enable and configure GPIO pins for the TM4C123 Tiva C LaunchPad.

Creating a New CCS Project for Tiva C LaunchPad

I have already explained how to create a new project in TM4C123 using CCStudio. You can create a similar project with blinky template and then modify it for this tutorial.

There are only 2 things we need to do to turn the blinky template into a new project:

  1. Delete everything from the blinky.c file, so it should be completely empty. We will write everything ourselves.
  2. Rename the following:
    • blinky.c → main.c, indicating that this is the main file for the project
    • blinky_css.cmd → linker.cmd, indicating that this is the linker file
    • blinky (Folder) → projectName (Folder)

The final modified project is shown in the image below.

Creating an Empty project in TI Launchpad CCStudio

Including TivaWare Driver Library

To make programming easier, we’ll use TivaWare, which provides ready-to-use driver functions like GPIOPinTypeGPIOOutput() and SysCtlPeripheralEnable().

Include TivaWare headers in your program:

#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "inc/hw_memmap.h"

These headers serve the following purpose:

Header FilePurposeExample Function or Macro
driverlib/sysctl.hControls system-level settings like clocksSysCtlPeripheralEnable()
driverlib/gpio.hConfigures and controls GPIO pinsGPIOPinWrite()
inc/hw_memmap.hDefines base addresses of peripheralsGPIO_PORTF_BASE

Enabling GPIO Clock in Code

Every GPIO port in the TM4C123 requires a clock before it can be used.
This clock is controlled by the System Control module, and you can enable it using the TivaWare function SysCtlPeripheralEnable().

Example:

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);   // Enable clock for Port F
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF));  // Wait until ready

This ensures that the GPIOF module is fully powered and ready to use before configuration.


Configuring Pins as Input or Output

Once the GPIO clock is enabled, you can configure the direction of each pin. Use TivaWare functions to set pins as input or output.

Example:

// Configure PF1, PF2, PF3 as output (LEDs)
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);

// Configure PF0 and PF4 as input (Switches)
GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4);

If you’re using the onboard push buttons, you should also enable internal pull-up resistors, since the switches are active LOW:

GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);

Now your GPIO pins are ready for digital input and output operations.

Writing Code for Digital Output (LED Control)

Controlling LEDs is the first step in learning how to use GPIO pins. With the TM4C123 Tiva C LaunchPad, you can easily turn LEDs on or off by writing to the appropriate GPIO pins.

Initialize GPIO Port and Direction

Before controlling LEDs, the corresponding GPIO port must be enabled, and the pins connected to LEDs must be configured as outputs.

In Code Composer Studio (CCS) with TivaWare, you can do this using the following steps:

  1. Enable the GPIO Port Clock
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);  // Enable clock for Port F
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF));  // Wait until ready
  1. Configure LED Pins as Output
    The TM4C123 LaunchPad has onboard LEDs connected to PF1 (Red), PF2 (Blue), PF3 (Green).
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);

Now the pins are ready to be driven HIGH or LOW.


Set or Clear Pin Output Value

Once a pin is configured as output, you can turn the LED on or off using the GPIOPinWrite() function.

  • Turn ON an LED: Write the pin HIGH
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_PIN_1);  // Turn ON Red LED
  • Turn OFF an LED: Write the pin LOW
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0);  // Turn OFF Red LED

You can control multiple LEDs at the same time by OR-ing the pin masks in the function call.

GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2, GPIO_PIN_1|GPIO_PIN_2);  // Turn ON LEds

Example Code to Blink LED using GPIO

Here’s a simple example that blinks the Red LED (PF1) continuously using a delay. The code combines system clock setup, GPIO output control, and a millisecond timer using SysTick interrupts to blink an LED reliably.

Using SysTick is preferred over simple delay loops because it allows accurate, interrupt-driven timing that won’t be affected by CPU speed changes. I have covered the usage of Delay in TM4C123G, you can check it out.

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "driverlib/systick.h"
#include "driverlib/interrupt.h"   // for IntMasterEnable


// System Clock Related Functions
void systemClockConfig (void)
{
    // Using MOSC 16MHz (External) -> PLL (400MHz) -> PLL (200MHz)/2.5 = 80MHz
    SysCtlClockSet(SYSCTL_XTAL_16MHZ|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_SYSDIV_2_5);
}

// SysTick Timer Related functions
volatile uint32_t msTicks = 0;

void SysTick_Handler(void)
{
    msTicks++;   // increment every millisecond
}

void delay_ms(uint32_t ms)
{
    uint32_t start = msTicks;
    while ((msTicks - start) < ms) {}
}

void SysTick_Init(void)
{
    SysTickPeriodSet(SysCtlClockGet() / 1000); // 1ms period
    SysTickIntRegister(SysTick_Handler);     // Register ISR
    SysTickIntEnable();                        // Enable SysTick interrupt
    SysTickEnable();                           // Start SysTick
}

int main(void)
{
    // Set system clock
    systemClockConfig();

    IntMasterEnable();  // enable master interrupt
    SysTick_Init();  // configure SysTick Timer

    // Enable GPIOF
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF));

    // Configure PF1 as output (Red LED)
    GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1);

    while(1)
    {
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_PIN_1);  // LED ON
        delay_ms(1000);  // Simple delay
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0);           // LED OFF
        delay_ms(1000);  // Simple delay
    }
}

This program demonstrates blinking an LED (PF1) on the TM4C123 Tiva C LaunchPad using SysTick-based delays and GPIO control.

  1. System Clock Configuration (systemClockConfig)
    Sets up the microcontroller to run at 80 MHz using the external 16 MHz crystal and the PLL. This ensures accurate timing for SysTick and peripheral operations.
  2. SysTick Timer for Millisecond Delay
    • SysTick_Init() sets up the SysTick timer to generate an interrupt every 1 ms.
    • SysTick_Handler() increments a global counter msTicks on each interrupt.
    • delay_ms() provides a blocking delay by comparing msTicks, allowing accurate timing without using simple loops.
  3. GPIO Initialization
    • The GPIO port F clock is enabled using SysCtlPeripheralEnable().
    • GPIOPinTypeGPIOOutput() configures PF1 (Red LED) as a digital output.
  4. Master Interrupts (IntMasterEnable)
    Enables global interrupts, which is required for SysTick interrupt to work.
  5. LED Blink Logic (in main)
    Inside the infinite loop:
    • GPIOPinWrite() turns the LED ON or OFF.
    • delay_ms(1000) introduces a 1-second delay between toggles.

Output Demonstration: LED Blinking on TM4C123

After writing and running the code, you can observe the Red LED (PF1) on the Tiva C LaunchPad turning ON and OFF every 1 second. This visually confirms that the GPIO output and SysTick-based delay are working correctly.

The GIF below illustrates the LED blinking in real time, showing a consistent 1-second ON/OFF pattern.

GIF showing the red LED (PF1) on TM4C123 Tiva C LaunchPad blinking on and off every 1 second

Writing Code for Digital Input (Push Button)

Reading a push button to control an LED is a fundamental way to learn digital input on the TM4C123 Tiva C LaunchPad. Here, we’ll use PF4 (SW1) as input and PF1 (Red LED) as output.

Configure GPIO Pin as Input and Use Pull-Up Resistor

Before reading the button, the pin must be configured as input, and an internal pull-up resistor must be enabled. This is necessary because the onboard buttons are active LOW.

// Configure PF4 as input (SW1) with internal pull-up
GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_4);
GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);

First set the PF4 as input using the function GPIOPinTypeGPIOInput. Next, the function GPIOPadConfigSet configures the electrical properties of a GPIO pin. It controls the drive strength and pad type.

Parameters Explained

  1. GPIO_PORTF_BASE
    • Specifies the base address of Port F, indicating which GPIO port we are configuring.
  2. GPIO_PIN_4
    • Indicates pin 4 of Port F (SW1 button on Tiva C LaunchPad).
  3. GPIO_STRENGTH_2MA
    • Sets the output drive strength to 2 milliamps.
    • For input pins, this is not critical, but TivaWare requires a strength value even for inputs.
  4. GPIO_PIN_TYPE_STD_WPU
    • Sets the pad type to standard with weak pull-up resistor.
    • This ensures the pin reads HIGH when the button is not pressed (because the button connects the pin to ground when pressed).

Example Code to Control LED with Button

This program demonstrates digital input on the TM4C123 Tiva C LaunchPad. A push button (SW1) is used to control the Red LED (PF1).

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/systick.h"
#include "driverlib/interrupt.h"

volatile uint32_t msTicks = 0;

void SysTick_Handler(void)
{
    msTicks++;   // increment every millisecond
}

void delay_ms(uint32_t ms)
{
    uint32_t start = msTicks;
    while ((msTicks - start) < ms) {}
}

void SysTick_Init(void)
{
    SysTickPeriodSet(SysCtlClockGet() / 1000); // 1ms period
    SysTickIntRegister(SysTick_Handler);
    SysTickIntEnable();
    SysTickEnable();
}

void systemClockConfig(void)
{
    SysCtlClockSet(SYSCTL_XTAL_16MHZ | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_SYSDIV_2_5);
}

int main(void)
{
    systemClockConfig();   // Set system clock
    IntMasterEnable();     // Enable global interrupts
    SysTick_Init();        // Initialize SysTick timer

    // Enable GPIO Port F
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF));

    // Configure PF1 as output (Red LED)
    GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1);

    // Configure PF4 as input (SW1) with internal pull-up
    GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_4);
    GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);

    while(1)
    {
        // Read the button state
        if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_4) == 0)   // Button pressed (active LOW)
            GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_PIN_1);  // Turn ON LED
        else
            GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0);           // Turn OFF LED
    }
}

The code follows the same style as the previous LED blink example, using SysCtlClock, SysTick timer, and TivaWare GPIO functions.

  • System Clock Setup (systemClockConfig)
    Sets the MCU to 80 MHz, ensuring reliable timing and peripheral operation.
  • SysTick Timer
    Although not required for button reading, SysTick is initialized to maintain a consistent millisecond counter, keeping the code structure consistent with the previous section.
  • GPIO Initialization
    • PF1 is configured as an output to drive the LED.
    • PF4 (SW1) is configured as an input with internal pull-up resistor, ensuring a HIGH logic level when the button is not pressed.
  • Button Control Logic
    Inside the infinite loop:
    • GPIOPinRead() checks the state of PF4.
    • When the button is pressed (logic LOW), the LED is turned ON.
    • When the button is released, the LED is turned OFF.

This simple program demonstrates how to combine digital input and output in real-time, letting you interact with the hardware using a button.


Output Demonstration: LED Controlled by Push Button

After running the code, you can observe the following behavior on the Tiva C LaunchPad:

  • Red LED (PF1) turns ON only when SW1 (PF4) is pressed.
  • The LED immediately turns OFF when the button is released.
  • This confirms that GPIO input reading and output control are working correctly.
GIF showing the red LED (PF1) on TM4C123 Tiva C LaunchPad turning on only when the SW1 push button (PF4) is pressed and turning off when released

Conclusion

In this tutorial, we covered the fundamentals of GPIO on the TM4C123 Tiva C LaunchPad. You learned how to configure pins as outputs to control LEDs and use the SysTick timer to create reliable millisecond delays. We also explored configuring GPIO pins as inputs to read push buttons, enabling internal pull-up resistors to handle active LOW buttons, and combining input and output to control an LED using a button.

By working through these examples, you now have a solid understanding of how to read from switches and control LEDs, which forms the foundation for most embedded projects. In the next tutorial, we will expand on this knowledge by introducing external interrupts, allowing buttons to trigger events without constant polling, making your code more efficient and responsive.

Browse More TM4C123G Tutorials

TM4C123G GPIO Project Download

Info

You can help with the development by DONATING Below.
To download the project, click the DOWNLOAD button.

TM4C123G GPIO FAQs

Subscribe
Notify of

0 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments