You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过DMA通道读取UART外设数据并写入队列

RP2040 基于DMA实现UART数据写入环形队列配置方案

以下是UART+DMA组件联动的完整配置逻辑,可实现无需CPU介入的UART数据自动接收:

1. UART外设基础配置

先完成UART的常规参数配置(波特率、数据位、停止位、校验位等),同时开启UART的DMA接收触发:

uart_set_dma_enabled(uart0, UART_DMARX, true);

2. DMA通道参数配置

利用RP2040 DMA的地址回绕特性适配环形缓冲区,配置项如下:

  • 选择任意空闲DMA通道,设置传输位宽为1字节,匹配UART FIFO的单数据位宽
  • 源地址设为对应UART的数据寄存器地址,配置为传输后地址不递增,保证每次都从固定寄存器位置读新数据
  • 目的地址设为提前申请的环形缓冲区首地址,开启写地址回绕功能,回绕大小和环形缓冲区大小一致。注意回绕大小必须为2的n次幂,最小值为16字节,缓冲区内存地址需要对齐到回绕大小
  • 触发源选择对应UART的RX就绪信号,UART0对应DREQ_UART0_RX、UART1对应DREQ_UART1_RX,设置为每收到一次触发信号就传输1字节

核心配置代码示例

// 定义环形缓冲区大小,必须是2的幂且≥16
#define UART_RX_BUF_SIZE 256
uint8_t uart_rx_buf[UART_RX_BUF_SIZE] __attribute__((aligned(UART_RX_BUF_SIZE)));

uint dma_chan = dma_claim_unused_channel(true);
dma_channel_config cfg = dma_channel_get_default_config(dma_chan);
// 源地址不递增,目的地址递增
channel_config_set_read_increment(&cfg, false);
channel_config_set_write_increment(&cfg, true);
// 绑定UART RX触发信号
channel_config_set_dreq(&cfg, DREQ_UART0_RX);
// 开启写地址回绕,第二个参数true代表写地址回绕,第三个参数为回绕大小的2次幂指数
channel_config_set_ring(&cfg, true, __builtin_ctz(UART_RX_BUF_SIZE));

// 配置并启动DMA
dma_channel_configure(dma_chan, &cfg,
                      uart_rx_buf,
                      &uart0_hw->dr,
                      UART_RX_BUF_SIZE,
                      true
);

3. 数据读取逻辑

DMA启动后会自动将UART收到的所有数据写入环形缓冲区,无需CPU干预。读取数据时只需维护一个独立的读指针,对比DMA通道当前的写地址偏移即可得到未读数据长度,读完后更新读指针即可。

注意:访问读写指针时建议添加原子操作保护,避免出现数据竞争导致的读取错误。

内容的提问来源于stack exchange,提问作者asynts

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 05:18:03