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

为什么搭载DMA的UART仅能接收到发送数据的最后一个字节?

调试会话截图
上图为UARTEx_RxEventCallback()函数代码,该函数预期实现持续接收串口字节的功能。从Hercules界面可以看到,发送测试数据123456789后仅能接收到最后一个字节。DMA配置为普通模式(非循环模式)、外设到内存方向、字节宽度,已开启NVIC中断,配置符合官方规范。
DMA UART任务初始化代码
上图为对应的主任务代码。


问题成因

  • DMA普通模式单次传输后自动失能,未及时重启接收
    普通模式下DMA完成一次预设长度的传输、或接收超时触发IDLE中断后,会自动关闭对应通道,不会自动启动下一次传输。你仅在初始化阶段调用了一次DMA接收启动函数,未在UARTEx_RxEventCallback()中处理完当前数据后重新启动DMA接收,后续串口数据无法写入DMA缓冲区,只能暂存于UART数据寄存器中,新数据到来后直接覆盖旧值,最终仅能读到最后一个字节。
  • DMA接收长度配置不合理
    如果启动DMA接收时设置的缓冲区长度为1,且处理回调时未及时将数据转存到其他缓存,也会导致新接收的字节始终覆盖缓冲区的首个地址,最终仅保留最后一个接收值。
  • 回调函数逻辑阻塞
    如果UARTEx_RxEventCallback()内处理逻辑耗时过长,导致下一个字节到来时DMA还未完成重启,也会出现数据丢失的情况。

修复方案

  1. 在UARTEx_RxEventCallback()的末尾重新调用UART DMA接收启动接口,比如HAL_UARTEx_ReceiveToIdle_DMA(&huart1, rx_buffer, BUFFER_SIZE),保证每次数据处理完成后立即启动下一轮接收。
  2. 根据业务需求设置合理的DMA接收缓冲区长度,处理数据时按实际接收的字节数读取,避免数据覆盖。
  3. 精简回调函数内的处理逻辑,耗时操作转移到主循环或独立任务中执行,避免阻塞DMA接收流程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 02:21:03