How to Use DMA with UART in Embedded C: Simple Guide
To use
DMA with UART in Embedded C, configure the UART peripheral and DMA controller to handle data transfers automatically. Set up DMA channels linked to UART TX and RX, enable DMA requests in UART, and start the DMA transfer to send or receive data without CPU intervention.Syntax
The basic steps to use DMA with UART in Embedded C include:
- Initialize UART peripheral.
- Configure DMA channel for UART TX or RX.
- Enable DMA requests in UART control registers.
- Start DMA transfer by setting source and destination addresses and data length.
This setup allows UART to trigger DMA transfers automatically.
c
/* Pseudocode syntax for UART DMA setup */
UART_Init();
DMA_Channel_Config(source_address, destination_address, data_length);
UART_Enable_DMA_Request();
DMA_Start();Example
This example shows how to send a string over UART using DMA on an STM32 microcontroller. It initializes UART and DMA, then starts a DMA transfer to send data without CPU load.
c
#include "stm32f4xx.h" char message[] = "Hello DMA UART!\r\n"; void UART_DMA_Init(void) { // Enable clocks for UART2 and DMA1 RCC->APB1ENR |= RCC_APB1ENR_USART2EN; RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN; // Configure UART2: 115200 baud, 8N1 USART2->BRR = 0x8B; // Assuming 16MHz clock USART2->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; // Configure DMA1 Stream6 for USART2_TX DMA1_Stream6->CR = 0; DMA1_Stream6->PAR = (uint32_t)&(USART2->DR); // Peripheral address DMA1_Stream6->M0AR = (uint32_t)message; // Memory address DMA1_Stream6->NDTR = sizeof(message) - 1; // Number of data DMA1_Stream6->CR = DMA_SxCR_DIR_0 | // Memory to peripheral DMA_SxCR_MINC | // Memory increment DMA_SxCR_TCIE | // Transfer complete interrupt enable DMA_SxCR_PL_1; // Priority high // Enable DMA request on USART2 TX USART2->CR3 |= USART_CR3_DMAT; // Enable DMA stream DMA1_Stream6->CR |= DMA_SxCR_EN; } int main(void) { UART_DMA_Init(); while (!(DMA1->HISR & DMA_HISR_TCIF6)) { // Wait for transfer complete } // Transfer complete, disable DMA stream DMA1_Stream6->CR &= ~DMA_SxCR_EN; while (1) {} }
Output
Hello DMA UART!
Common Pitfalls
Common mistakes when using DMA with UART include:
- Not enabling DMA requests in UART control registers.
- Incorrectly setting DMA source or destination addresses.
- Forgetting to enable the DMA stream/channel.
- Not handling transfer complete interrupts or flags.
- Using wrong data length causing incomplete transfers.
Always verify peripheral clocks and interrupt priorities.
c
/* Wrong: DMA not enabled in UART */ USART2->CR3 = 0; // DMA request disabled /* Right: Enable DMA request for TX */ USART2->CR3 |= USART_CR3_DMAT;
Quick Reference
Tips for using DMA with UART:
- Enable peripheral clocks before configuration.
- Set DMA direction correctly (memory-to-peripheral for TX, peripheral-to-memory for RX).
- Enable UART DMA requests in
CR3register. - Use memory increment mode for buffers.
- Check and clear DMA transfer complete flags.
Key Takeaways
Configure UART and DMA peripherals properly before starting transfers.
Enable DMA requests in UART control registers to link UART and DMA.
Set correct source, destination, and data length in DMA for reliable transfers.
Always check DMA transfer complete flags to know when transfer ends.
Common errors include missing DMA enable in UART and wrong addresses.