How to Implement UART Receive Interrupt in Embedded C
To implement a
UART receive interrupt in Embedded C, first enable the UART receive interrupt in the UART control register and configure the interrupt vector to call your interrupt service routine (ISR). Inside the ISR, read the received data from the UART data register to clear the interrupt flag and process the data as needed.Syntax
The basic steps to implement UART receive interrupt are:
- Enable UART receive interrupt in the UART control register.
- Write an Interrupt Service Routine (ISR) to handle the interrupt.
- Inside the ISR, read the UART data register to clear the interrupt flag.
- Process the received data as needed.
c
void UART_Init(void) { // Enable UART receiver and its interrupt UART_CTRL_REG |= (1 << RX_ENABLE_BIT) | (1 << RX_INT_ENABLE_BIT); // Enable global interrupts ENABLE_GLOBAL_INTERRUPTS(); } // UART Receive Interrupt Service Routine void UART_RX_ISR(void) { char received_char = UART_DATA_REG; // Read received data // Process received_char as needed }
Example
This example shows how to initialize UART with receive interrupt and handle incoming data by storing it in a buffer.
c
#include <stdint.h> #include <stdbool.h> #define UART_CTRL_REG (*(volatile uint8_t*)0x4000) #define UART_DATA_REG (*(volatile uint8_t*)0x4001) #define UART_STATUS_REG (*(volatile uint8_t*)0x4002) #define RX_ENABLE_BIT 0 #define RX_INT_ENABLE_BIT 1 #define RX_READY_BIT 0 volatile char rx_buffer[64]; volatile uint8_t rx_index = 0; void ENABLE_GLOBAL_INTERRUPTS(void) { // Platform specific code to enable global interrupts } void UART_Init(void) { UART_CTRL_REG |= (1 << RX_ENABLE_BIT) | (1 << RX_INT_ENABLE_BIT); ENABLE_GLOBAL_INTERRUPTS(); } // UART Receive Interrupt Service Routine void UART_RX_ISR(void) { if (UART_STATUS_REG & (1 << RX_READY_BIT)) { char received_char = UART_DATA_REG; // Read clears interrupt flag if (rx_index < sizeof(rx_buffer)) { rx_buffer[rx_index++] = received_char; } } } int main(void) { UART_Init(); while (true) { // Main loop can process rx_buffer or sleep } return 0; }
Output
No direct output; UART receive interrupt stores incoming characters in rx_buffer.
Common Pitfalls
- Not enabling global interrupts after enabling UART receive interrupt.
- Failing to read the UART data register inside the ISR, which prevents clearing the interrupt flag and causes repeated interrupts.
- Accessing shared data (like buffers) without proper synchronization if used outside ISR.
- Not configuring the interrupt vector or ISR correctly, so the interrupt never triggers.
c
/* Wrong: Not reading UART_DATA_REG inside ISR, interrupt flag not cleared */ void UART_RX_ISR(void) { // Missing read of UART_DATA_REG // Interrupt flag remains set, causing repeated interrupts } /* Correct: Read UART_DATA_REG to clear interrupt flag */ void UART_RX_ISR(void) { char received_char = UART_DATA_REG; // Clears interrupt flag // Process received_char }
Quick Reference
| Step | Description |
|---|---|
| Enable UART RX interrupt | Set RX interrupt enable bit in UART control register |
| Enable global interrupts | Allow CPU to respond to interrupts |
| Write ISR | Read UART data register to clear interrupt flag and handle data |
| Process data | Use received data as needed in main program or ISR |
| Avoid pitfalls | Always clear interrupt flag and synchronize shared data |
Key Takeaways
Always enable UART receive interrupt and global interrupts to allow ISR execution.
Inside the ISR, read the UART data register to clear the interrupt flag and get received data.
Configure the interrupt vector properly so the ISR is called on UART receive events.
Avoid missing the data register read inside ISR to prevent repeated interrupts.
Use buffers carefully and synchronize access if shared between ISR and main code.