š 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
Nmilliseconds)
-
-
Use
SysTickas 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 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
BRRregisterBRR = SystemCoreClock / BaudRate(33.8.5) -
Disable overrun in the
CR3register:OVRDIS(33.8.4) -
Enable peripheral, receiver , and transmitter (33.8.1)
UE,RE,TEin theCR1register -
If interrupt is needed SET
RXNEIEin theCR1register (33.8.1) -
CLEAR receiving flag, just in case:
RXFRQin theRQRregister. This enables to discard the received data without reading them, and avoid an overrun condition. (33.8.8)
Transmitting a Byte
-
Wait for the
TXFNFflag in theISRregister to be SET to1(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
RXFNEflag in theISRregister is SET to1(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 theCR1 -
Enable the
NVIC IRQcallingNVIC_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]