Chapter 5: USART with Interrupts

šŸ“š CMPE2250: Lesson — USART Reception Using Interrupts + Timeout (STM32G0)

šŸŽÆ Learning Objectives

Students will be able to:

  • Configure the USART peripheral for interrupt‑driven reception

  • Implement a circular or linear receive buffer

  • Detect end‑of‑packet using either:

    • A terminator character (\r), or

    • A timeout (no characters received for N milliseconds)

  • Use SysTick as a millisecond timebase

  • Validate their implementation using a serial terminal


1ļøāƒ£ UART Protocol Fundamentals (from CMPE1250)

What is UART?

UART (Universal Asynchronous Receiver/Transmitter) is a serial communication protocol that transmits data one bit at a time over a single wire. It’s asynchronous, meaning no shared clock — both devices must agree on timing.

UART

UART Frame Structure

Component Description
Start Bit Always 0 (low). Signals the beginning of a frame
Data Bits Usually 8 bits (can be 5–9)
Parity Bit Optional error-checking bit
Stop Bit(s) One or two bits set to 1 (high)

Example: A frame with 8 data bits, no parity, and 1 stop bit:

START D0 D1 D2 D3 D4 D5 D6 D7 STOP

Baud Rate

  • Baud rate = bits per second (bps)
  • Common values: 9600, 115200
  • STM32 formula:

    BRR = (uint32_t)((float)SystemCoreClock / BaudRate + 0.5f)


STM32 USART Registers (Chapter 33 RM)

Register Purpose
USART_CR1 Enable USART, TX, RX, interrupts
USART_CR3 Overrun disable
USART_BRR Baud rate configuration
USART_ISR Status flags (TXE, RXNE, etc.)
USART_TDR Transmit data register
USART_RDR Receive data register
USART_RQR Request register (clear RX flags)

Minimum steps to Initialize the USART/UART

  • Before configuring the peripheral, the proper alternate function must me anabled to have the Tx and Rx PINs in the GPIO port.

  • Set Baud Rate in the BRR register

    BRR = SystemCoreClock / BaudRate (33.8.5)

  • Disable overrun in the CR3 register: OVRDIS (33.8.4)

  • Enable peripheral, receiver , and transmitter (33.8.1)

    UE, RE, TE in the CR1 register

  • If interrupt is needed SET RXNEIE in the CR1 register (33.8.1)

  • CLEAR receiving flag, just in case: RXFRQ in the RQR register. This enables to discard the received data without reading them, and avoid an overrun condition. (33.8.8)

Transmitting a Byte

  • Wait for the TXFNF flag in the ISR register to be SET to 1 (33.8.9)

  • Write data into the transmit data register: TDR (33.8.13)

Receiving a Byte

  • When a byte has been received and is ready to be read, the RXFNE flag in the ISR register is SET to 1 (33.8.9)

  • Read the byte from the receive data register RDR (33.8.12)

2ļøāƒ£ Why Interrupt‑Driven Reception?

Polling USART->RDR works for simple demos, but it fails when:

  • The CPU is busy doing other tasks
  • Bytes arrive faster than the polling loop checks
  • You need to process variable‑length packets

Interrupt‑driven reception solves this by:

  • Triggering an interrupt every time a byte arrives
  • Copying the byte into a buffer immediately
  • Returning to the main loop without blocking

This is the foundation for all real embedded communication.

3ļøāƒ£ USART Receiving with interrupts

To enable interrupt with the USART peripheral, these steps must be followed:

  • Enable the RXNEIE (BIT5) bit in the CR1

  • Enable the NVIC IRQ calling NVIC_EnableIRQ(IRQn) (e.g., NVIC_EnableIRQ(USART2_LPUART2_IRQn)).

  • Code the ISR associated with the peripheral’s vector. (e.g., void USART2_LPUART2_IRQHandler(void)).

  • In the ISR, clear the flag accordingly. For the USART, it gets clared automatically when the data is read from the

RDR register or when the data is discared (flushed, e.g., USART2->RQR |= USART_RQR_RXFRQ)

  • In the ISR, clear NVIC pending calling NVIC_ClearPendingIRQ(IRQn). (e.g. NVIC_ClearPendingIRQ(USART2_LPUART2_IRQn))

4ļøāƒ£ USART Receiving Timeout implementation

4.1 Using the Sytick Timer

    flowchart TD
        A[Byte arrives at USART] --> B[USART ISR]
        B --> C[Store byte in buffer]
        C --> D[receiving = 1]
        D --> E[Reset timeout counter]

        subgraph SysTick ISR
            F[Every 1 ms]
            F --> G[If receiving]
            G --> H[Increment timeout counter]
            H --> I{Counter > TIMEOUT?}
            I -->|Yes| J[packetComplete = 1]
            I -->|No| K[Continue]
        end

        J --> L[Main loop processes packet]
        L --> M[Clear buffer]