Meet the MSP430 USCI Module

The Universal Serial Communication Interface (USCI) is a powerful hardware module built into the MSP430G2553. It handles the low-level details of serial communication, so you don’t have to manually shift out bits or time every clock cycle in software.

The G2553 includes two distinct USCI modules, each specialized for different protocols:

  • USCI_A0: Supports UART (used to talk to a PC over serial) and SPI

  • USCI_B0: Supports I²C (used to talk to sensors, displays, etc.) and SPI

Each module has its own dedicated set of control and data registers, like:  

  • UCA0TXBUF and UCA0RXBUF for transmitting and receiving characters over UART

  • UCB0CTL1, UCB0I2CSA, and UCB0TXBUF for managing I²C communication

  • UCAxBR0, UCAxBR1, and UCAxMCTL for setting baud rates and modulation

Because these modules are hardware-driven, your code only needs to configure a few registers and load or read data — the USCI takes care of the rest.

Best of all, the two modules work independently, so you can use UART on USCI_A0 and I²C on USCI_B0 at the same time — giving your MSP430 serious multitasking ability for real-world embedded systems..

In this two-part tutorial, we'll explore both "flavors" of the USCI module on the MSP430G2553 by building two classic "Hello World" projects. In Part 1, we'll use USCI_A0 to send a message over UART to a PC terminal, demonstrating how to configure the UART registers and establish basic serial communication. In Part 2, we'll switch to USCI_B0 to communicate with an I²C LCD, showing how to send data over the I²C bus and display a message on a physical screen. Together, these projects will give you a practical introduction to the MSP430's built-in serial communication capabilities — both digital and visual.

Part 1: The UART USCI_A

UART (Universal Asynchronous Receiver/Transmitter) is one of the simplest and most widely used serial communication protocols. It allows two devices to send and receive data over just two lines: TX (transmit) and RX (receive) — no clock signal needed. UART is perfect for sending text between a microcontroller and a PC, making it a great first step in learning how to communicate with external devices.

On the MSP430G2553, UART communication is handled by the USCI_A0 module — one of two serial interface engines built into the chip. This module takes care of formatting, timing, and buffering the data, so you only need to configure a few registers and feed it bytes.

In this tutorial, we’ll use the USCI_A0 module to send a simple "Hello, world!" message from the MSP430 to your computer over UART. You’ll connect the MSP430 to your PC using a USB-to-Serial adapter, and use a program like PuTTY to view the message on your screen.

PuTTY is a free and lightweight terminal emulator that lets your computer "listen" to serial ports. Once connected to the correct COM port at the right baud rate (9600 bps), it will display anything the MSP430 sends — making it perfect for testing UART output. If you don't have putty installed on your system you can get it for free here.

By the end of this tutorial, you’ll understand how to set up UART on the MSP430, write directly to the USCI registers, and send real data over a serial line to your PC. Below is the USCI_A Module block diagram in UART mode. Note their are only two lines UC0RX (Receive) and UCOTX (Transmit). These lines are located on pins P1.1 and P1.2.

To get the MSP430G2553 talking over UART, we need to configure a handful of registers in the USCI_A0 module. The first and most important is UCA0CTL1, which controls the state of the USCI module. We begin by putting the USCI into a software reset state (UCSWRST) so we can safely configure it. In this same register, we also select the clock source for the baud rate generator—SMCLK in our case—by setting the UCSSEL_2 bits.

Next, we set the baud rate using UCA0BR0 and UCA0BR1, which together define the division factor for the UART bit timing. For a 1 MHz clock and a target of 9600 baud, these are typically set to UCA0BR0 = 104 and UCA0BR1 = 0. The UCA0MCTL register further fine-tunes the baud rate using modulation (in our case, UCBRS0 is set for small adjustments). Once configuration is complete, we clear the software reset bit in UCA0CTL1, allowing the USCI state machine to start running. Data is sent by writing to UCA0TXBUF, and we check if it's ready using the UCA0TXIFG flag inside the general-purpose IFG2 register. These few registers are all it takes to initialize UART and begin transmitting data from the MSP430 to your PC.

Register Description
UCA0CTL0 Control register 0 – sets UART parameters like parity, bit order, stop bits, etc.
UCA0CTL1 Control register 1 – used to enable/disable the module (UCSWRST), and select clock source (UCSSELx).
UCA0BR0 Baud rate control register low byte – sets part of the divisor for baud rate generation.
UCA0BR1 Baud rate control register high byte – sets the upper part of the baud rate divisor.
UCA0MCTL Modulation control – fine-tunes the baud rate with modulation stage settings (UCBRSx, UCBRFx).
UCA0STAT Status register – provides flags for errors (framing, parity, overrun) and loopback control.
UCA0RXBUF Receive buffer – holds the most recently received byte (read-only).
UCA0TXBUF Transmit buffer – write a byte here to transmit it (write-only).
UCA0ABCTL Auto-baud control – used in special auto-baud detection scenarios (rarely used).
UCA0IRTCTL / UCA0IRRCTL Infrared control – only used for IrDA (infrared) mode, typically unused in basic UART applications.

Before you start feeling overwhelmed by all the configuration bits inside the USCI module, take a breath — using UART on the MSP430 is actually pretty simple. While the USCI_A0 module has quite a few registers, you only need to work with a handful of them to get UART up and running. The rest are for more advanced features (like SPI or infrared communication), which we won’t touch in this basic "Hello, world!" example.

  1. UCA0CTL1 – USCI_A0 Control Register 1: This is the first register we touch, and it’s critical. It controls the software reset (UCSWRST) that lets us safely configure the module. It’s also where we pick the clock source for the UART baud rate generator — typically SMCLK, using UCSSEL_2.

  2. UCA0BR0 and UCA0BR1 – Baud Rate Registers: These two registers define the divisor used to slow down the clock signal to match your desired baud rate (usually 9600 bps). Since the clock runs at 1 MHz in this tutorial, we set UCA0BR0 = 104 and UCA0BR1 = 0, which gives a divisor of 104.

  3. UCA0MCTL – Modulation Control: This register fine-tunes the baud rate using a modulation stage. We don’t need anything fancy here — just set UCBRS0, which provides a small timing correction for better accuracy when dividing 1 MHz into 9600 baud.

  4. UCA0TXBUF – Transmit Buffer: This is where you write a single character to send it over UART. Once the transmit flag is set, you drop a byte into UCA0TXBUF, and the USCI module handles the rest

  5. IFG2 – Interrupt Flag Register (Contains UCA0TXIFG): We don’t use interrupts in this example, but we still check this register’s flag bit UCA0TXIFG to know when the transmit buffer is ready. It ensures we don’t try to send another character before the last one is done.

That’s it — just a few well-behaved registers and you’re up and talking to the outside world. The USCI_A0 module is extremely capable, but the basics are straightforward when you stick to the essentials. And because we’re only using UART mode, we don’t have to worry about the SPI-related bits in UCA0CTL0, or any of the special modes in UCA0STAT or UCA0ABCTL.

As always, make sure your UART pins (P1.1 and P1.2) are configured properly, and don’t forget to share ground with your USB-to-Serial adapter. With that, you're good to go. Below is an image showing the jumper wires needed to configure P1.1 and P1.2 properly, so UART communication with your computer can happen - don't stop the magic! Note the sideways jumper positions.

The UART "Hello World" Code and Program Flow

What This Code Does!

This example uses the USCI_A0 module on the MSP430G2553 to send and receive data over a UART connection with a PC. When the program starts, it prompts the user to enter their name using a serial terminal (like PuTTY). Once the user types their name and presses Enter, the MSP430 replies with a friendly greeting — "Hello, [Name]!" — over the same serial connection.

All of the communication happens using hardware-level UART: the USCI module handles baud rate timing, buffering, and character-level transmission. We configure the module for 9600 baud using SMCLK, and use simple polling (not interrupts) to send and receive data one character at a time. The terminal interface provides a basic but useful way to interact with the MSP430 — great for debugging, data logging, or just getting started with serial communication.

Equipment You Need

  • MSP-EXP430G2ET Development Kit

  • MSP430G2553

  • Open Putty Terminal

Before you open the Putty instnace confirm the COM port your MSP430 is using in the Device Manager.

The FLOW

The program flow for this project is structured into 5 main parts. While it follows the same general layout as the other tutorials, this one focuses on using the USCI_A0 module to set up a basic UART communication channel between the MSP430 and a PC. The user is prompted to enter their name over a serial terminal, and the MSP430 replies with a personalized greeting.

  •  MSP430 library declaration and program definitions

    This section includes the standard <msp430.h> header, along with global variable declarations and function prototypes. In this example, we declare a character buffer to store the user's name and set up helper functions for sending and receiving characters over UART.

  • Function Prototypes

    This section lists the function prototypes for the UART helper routines. These include uart_send_string() to transmit strings, uart_receive_char() to read individual characters, and uart_receive_string() to collect user input into a buffer.

  •  Main Routine  

    • Turn off Watchdog Timer

      The watchdog timer is disabled at startup to prevent unexpected resets during development or communication delays

    • Set the clock speed

      Loads factory calibration constants to configure the digitally controlled oscillator (DCO) for 1 MHz. This clock is used as the timing source for the UART baud rate generator.

    • Set Up the USCI_A0 Module

      The UART module is configured by putting the USCI into reset (UCSWRST), selecting SMCLK as the clock source, setting the baud rate registers (UCA0BR0, UCA0BR1), enabling modulation via UCA0MCTL, and then releasing the reset to begin operation.

    • Send and Receive UART Data

      The user is prompted to enter their name. As characters are received one by one, they’re echoed back and stored in a buffer. Once Enter is pressed, the MSP430 sends a greeting using the entered name.

    • Enter "Forever" Loop

      After displaying the greeting, the program enters an infinite loop. No interrupts or low-power modes are used in this basic example — the goal is simply to demonstrate one-time input/output over UART.

  • Function Definitions

    ADC10 Interrupt Service Routine

    This section includes the implementations of the UART helper functions. These use polling to check flags in IFG2 for transmit (UCA0TXIFG) and receive (UCA0RXIFG) readiness, and move data into or out of the UCA0TXBUF and UCA0RXBUF registers as needed.

The UART Code

When running the code make sure a putty window is open and connected to the right COM port.


//----------------Step 1---------------------------------
// Library Declaration
//-------------------------------------------------------
#include <msp430.h>

//----------------Step 2---------------------------------
// Function prototypes:
// uart_send_string - sends a null-terminated string over UART
// uart_receive_char - blocks and receives a single char from UART
// uart_receive_string - receives a string from UART with echo and stores it
//-------------------------------------------------------
void uart_send_string(const char *str);
char uart_receive_char(void);
void uart_receive_string(char *buffer, unsigned int max_len);

/**---------------Step 3---------------------------------
 * Main Routine
 **-----------------------------------------------------*/
void main(void)
{
    char name[40];            // Buffer to store user name input

    //-----Step 3.i Turn off Watchdog Timer----------------->
    WDTCTL = WDTPW | WDTHOLD;           // Stop watchdog timer

    //-----Step 3.ii Set Clock Speed of MSP430-------------->
    BCSCTL1 = CALBC1_1MHZ;              // Set DCO to 1 MHz calibration constant
    DCOCTL = CALDCO_1MHZ;               // Set DCO step and modulation

    //-----Step 3.iii Setup UART pins----------------------->
    P1SEL  |= BIT1 + BIT2;              // Select UART function for P1.1 and P1.2
    P1SEL2 |= BIT1 + BIT2;              // Select UART function for P1.1 and P1.2

    //-----Step 3.iv Configure USCI_A0 module for UART------->
    UCA0CTL1 |= UCSWRST;                // Put USCI in reset state for configuration
    UCA0CTL1 |= UCSSEL_2;               // Use SMCLK as clock source (1 MHz)

    UCA0BR0 = 104;                      // Set baud rate to 9600 (low byte)
    UCA0BR1 = 0;                        // Set baud rate to 9600 (high byte)
    UCA0MCTL = UCBRS0;                  // Modulation: UCBRSx = 1 for baud rate tuning

    UCA0CTL1 &= ~UCSWRST;               // Initialize USCI state machine (release from reset)

    //-----Step 3.v Prompt user for name-------------------->
    uart_send_string("Enter your name (max 39 chars): ");

    //-----Step 3.vi Receive user input (using subroutine)-->
    uart_receive_string(name, sizeof(name));

    //-----Step 3.vii Send greeting------------------------->
    uart_send_string("\r\n Hello, ");
    uart_send_string(name);
    uart_send_string("!\r\n");

    //-----Step 3.viii Loop forever-------------------------->
    while (1) {
        // MCU can sleep or wait here
    }
}

/*----------------Step 4----------------------------------
// Function Definitions
 *-------------------------------------------------------*/

// Send a null-terminated string over UART
void uart_send_string(const char *str)
{
    while (*str) {
        while (!(IFG2 & UCA0TXIFG));   // Wait until TX buffer is ready
        UCA0TXBUF = *str++;            // Send character
    }
}

// Blocking receive a single character from UART
char uart_receive_char(void)
{
    while (!(IFG2 & UCA0RXIFG));       // Wait until a character is received
    return UCA0RXBUF;                  // Read and return received character
}

// Receive a string from UART with echo, store in buffer up to max_len - 1 chars
void uart_receive_string(char *buffer, unsigned int max_len)
{
    unsigned int i = 0;
    while (1) {
        char c = uart_receive_char();

        // Break on carriage return or newline
        if (c == '\r' || c == '\n' || i >= max_len - 1) {
            break;
        }

        // Echo the character
        while (!(IFG2 & UCA0TXIFG));
        UCA0TXBUF = c;

        buffer[i++] = c;
    }

    buffer[i] = '\0';  // Null-terminate string
}

Part 2: The I2C USCI_B

By enabling the Timer A output on P2.2 and throwing the corresponding PWM signal into a resistor capacitors series combination, we will be able to turn our PWM signal into a ruff DC equivalent of the DC signal on the potentiometer. Of course it's not exactly the same, in fact, if you place a scope across the capacitor you'll see a charging and discharging of the cap voltage, which can approximate our potentiometer voltage, but it's certainly not an exact replica of it.

To Enable the Timer A output on P2.2 add the following lines of code just below line 29:

P2DIR |= BIT2;
P2SEL |= BIT2;

In addition to the above code, you have to attach the RC circuit as shown in the figure below, and then you'll have a rough DAC of the DC signal on the potentiometer.

All Tutorials Must End

When I first started working with the USCI module, it felt a bit like a black box—UART, I²C, SPI... all packed into one interface, each with its own quirks and registers. But once you separate the two modules (USCI_A0 for UART and USCI_B0 for I²C) and walk through a real-world example for each, the fog clears up fast. Sending a simple message to a terminal and getting text to appear on an I²C LCD are great stepping stones into embedded communication. This isn’t meant to be a deep-dive into every protocol feature, but a practical walkthrough to help you get your MSP430 talking to the outside world. If you get stuck or something’s not behaving the way you expect, feel free to reach out — I’m happy to help. Good luck, and keep building!