news 2026/5/10 14:24:22

STM32 DMA请求映射关系图解说明

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32 DMA请求映射关系图解说明

搞懂STM32的DMA请求映射,从此数据搬运不靠CPU

你有没有遇到过这样的场景:ADC在高速采样,UART在拼命发数据,SPI连着一块高速传感器……结果CPU被中断“淹没了”,程序卡顿、响应迟钝,甚至开始丢帧?

别急——问题可能不在代码写得差,而在于你还在用“人拉肩扛”的方式搬数据。真正高效的嵌入式系统,懂得把脏活累活交给DMA(Direct Memory Access)来干。

今天我们就来深挖一个关键但常被忽视的话题:STM32中DMA请求到底是怎么“连”到外设上的?为什么有时候配置了DMA却没反应?

这不是简单的寄存器填空题,而是一张隐藏在芯片内部的“交通图”。搞清这张图,你就掌握了让数据自动流动的钥匙。


为什么我们需要DMA?

先说个现实:CPU很忙,也很贵。让它每收到一个字节就跳一次中断,等于让CEO去前台接快递——效率低、成本高。

以ADC为例,假设你要做10kS/s的连续采样:
- 每100μs触发一次转换;
- 每次转换完成产生中断;
- CPU从中断进入、保护现场、读取数据、退出中断……这一套流程下来,哪怕只花几个微秒,也已经占用了相当一部分时间。

更别说还有UART、SPI、定时器等各种外设也在抢中断资源。

DMA的作用就是:当外设有数据要传时,它自己动手,从内存到外设或反过来,直接搬,不打扰CPU。

整个过程就像地铁系统——乘客(数据)上车(触发请求),列车(DMA通道)自动运行(传输),到站后广播一声“到了”(中断通知),乘客下车处理即可,司机全程无需人工干预。


STM32里的DMA架构长什么样?

STM32系列普遍配备两个DMA控制器:DMA1 和 DMA2。它们不是完全对等的。

  • DMA1:通常用于低速外设,比如UART2/3、I2C1/2、TIMx等。
  • DMA2:往往分配给高速或高优先级外设,如ADC1、SDIO、Ethernet、SPI1等。

以经典的STM32F407VG为例:
- DMA1 有 7 个通道
- DMA2 也有 7 个通道
- 总共 14 个可用DMA通道

每个通道可以独立配置源地址、目标地址、数据宽度(8/16/32位)、是否自增、传输方向和模式(单次、循环、双缓冲)。

但最关键的一点是:每个通道只能服务特定的外设请求源——这就是所谓的“DMA请求映射”。


外设发出的DMA请求,是怎么找到对应通道的?

想象一下:ADC1转换完成了,想把结果通过DMA送到内存。它是怎么“告诉”DMA控制器的?

这个过程其实是一条硬连线的路径,由ST公司在芯片设计阶段就固定好了。你可以把它理解为“预埋的信号线”。

请求映射的本质:一张静态对照表

在绝大多数STM32型号(如F1/F4/L4系列)中,DMA请求映射关系是固定的,记录在数据手册的“DMA Request Mapping Table”里。

举几个常见例子(基于STM32F407):

外设功能对应DMA控制器通道号
ADC1DMA2Channel 0
USART1_TXDMA2Channel 5
SPI1_RXDMA2Channel 2
TIM1_CH1DMA1Channel 2
DAC1DMA1Channel 3

这意味着:
- 如果你想用DMA传USART1发送的数据,必须使用DMA2_Channel5
- 如果你误用了DMA1_Channel5,哪怕寄存器配得再正确,也不会有任何传输发生

这就像坐飞机——你买了北京飞上海的票,就不能指望在广州登机还能上同一架航班。

📌重点提醒:很多初学者调试DMA失败,原因就是查错了映射表!一定要根据你的具体芯片型号查阅官方文档(如DS1894《STM32F407xx Datasheet》Table 64)。


那这些请求是怎么“接通”的?背后发生了什么?

我们来看一个典型的DMA传输流程,拆解每一步发生了什么:

步骤1:外设使能DMA请求

以ADC为例,在ADC_CR寄存器中有一个位叫DMAEN。一旦置位,表示:“每次转换完成后,请向DMA发个信号。”

ADC1->CR |= ADC_CR_DMAEN; // 启用DMA请求

此时,ADC内部的状态机会在每次EOC(End of Conversion)到来时,拉高DMA请求信号线。

步骤2:请求信号送达指定DMA通道

这条信号线物理上连接到了DMA2_Channel0的输入端。DMA控制器检测到有效请求后,会检查该通道是否已启用、是否有更高优先级任务正在执行。

步骤3:DMA启动传输

一旦仲裁通过,DMA开始工作:
- 从外设数据寄存器(如ADC1->DR)读取数据
- 写入预先设定的内存地址(如数组adc_buffer[]
- 地址递增(如果配置了MINC_ENABLE
- 直到达到设定的传输数量

全过程不需要CPU参与。

步骤4:完成通知(可选)

传输结束后,DMA可以触发中断,通知CPU:“我干完了。”这时CPU才介入处理数据,比如做滤波、上传、显示等操作。


关键参数你真的懂吗?

除了“哪个外设连哪个通道”,还有一些细节直接影响DMA能否正常工作。

✅ 请求线编号(Request Line Number)

有些高级系列(如H7、L5)引入了统一编号机制。例如:
- ADC1 → Request #0 on DMA2
- DAC1 → Request #6 on DMA1

这个编号用于配置CHSEL[3:0]字段(在支持的选择器中)。虽然F4系列大多是固定绑定,但在HAL库中仍需通过hdma.Init.Request = DMA_REQUEST_ADC1明确指定请求源。

✅ 数据传输方向必须匹配

每个DMA通道支持三种方向:
- 外设 → 内存(如ADC采集、SPI接收)
- 内存 → 外设(如UART发送、DAC输出)
- 内存 ↔ 内存(仅部分通道支持,且通常需要软件触发)

如果你把ADC配置成“内存到外设”,那永远等不到数据。

✅ 通道优先级设置很重要

多个外设同时请求DMA怎么办?靠仲裁器按优先级决定顺序。

每个通道可设:
- 非常低
- 低
- 中
- 高

建议原则:
- 实时性要求高的任务设为高优先级(如音频播放)
- 批量传输类任务设为中低优先级
- 避免多个高优先级通道争抢导致饥饿


固定映射太死板?ST也想到了——DMAMUX来了!

前面说的都是“老派”STM32的做法:请求和通道一一对应,改不了。

但从STM32G0、H7、L5、WB 等新一代系列开始,ST引入了一个强大的新模块:DMAMUX(DMA Multiplexer),彻底改变了游戏规则。

DMAMUX 是什么?

你可以把它看作是一个“DMA路由器”或者“交换机”。它位于外设和DMA控制器之间,允许你用软件动态指定某个DMA通道接收哪个外设的请求

比如原来只有ADC1能连DMA1_Channel1,现在你可以让:
- ADC1 → DMA1_Channel1
- 或者 DAC2 → DMA1_Channel1
- 或者 TIM6_TRGO → DMA1_Channel1

全凭你在代码里配置!

它带来了哪些好处?

优势说明
⚡ 设计灵活性大幅提升不再受限于封装引脚或默认映射冲突
🔁 支持请求复用多个外设可分时共享同一个DMA通道
🕰 精确同步控制可配合定时器TRGO信号实现周期性触发
🧩 更适合复杂系统整合尤其适用于多功能复用场景

来看个真实代码示例:用DMAMUX绑定ADC1到任意DMA通道

DMA_HandleTypeDef hdma_adc; DMAMUX_Channel_TypeDef *dmamux_channel = DMAMUX1_Channel0; // 控制DMA1_Stream1 // 配置DMA基本参数 hdma_adc.Instance = DMA1_Stream1; hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE; hdma_adc.Init.MemInc = DMA_MINC_ENABLE; hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; hdma_adc.Init.Mode = DMA_CIRCULAR; hdma_adc.Init.Priority = DMA_PRIORITY_HIGH; if (HAL_DMA_Init(&hdma_adc) != HAL_OK) { Error_Handler(); } // 配置DMAMUX:将ADC1请求路由到当前DMA通道 dmamux_channel->CCR &= ~DMAMUX_CCR_DMAREQ_ID; // 清除原选择 dmamux_channel->CCR |= DMAMUX_CCR_DMAREQ_ID_12; // 设置为ADC1 (ID=12)

📌 注意这里的DMAREQ_ID_12是ADC1在DMAMUX中的请求编号,具体数值需查对应芯片参考手册。

有了这段代码,即使硬件上原本不允许,你也能让ADC1走DMA1_Stream1完成数据搬运。


典型应用场景:实时音频采集系统

让我们看看DMA请求映射如何在实战中发挥作用。

设想一个麦克风采集语音的应用:

[麦克风] ↓ [ADC] → 触发DMA请求 → [DMA控制器] ⇄ [SRAM双缓冲] ↓ [半满中断] → [CPU进行FFT处理] ↓ [SPI发送至DSP]

如果没有DMA:
- 每次ADC转换完成都要进中断
- CPU频繁被打断,无法及时处理算法
- 极易造成音频断续或溢出

用了DMA + 双缓冲后:
- ADC持续转换,DMA自动搬运数据
- 当前缓冲区满,切换到另一个,并触发中断
- CPU只需在中断里处理一批数据,其余时间可休眠或跑其他任务

实测效果:CPU负载从 >70% 降到 <10%,系统稳定性显著提升。


常见“坑点”与避坑秘籍

❌ 痛点1:DMA没反应?检查这几点!

  1. 外设是否开启了DMA请求?
    - 如USART_CR3 |= USART_CR3_DMAT;
  2. DMA通道是否对应正确的请求映射?
    - 查手册!不要凭记忆
  3. DMA时钟是否开启?
    -__HAL_RCC_DMA1_CLK_ENABLE();
  4. NVIC中断是否使能?(若需中断)
    -HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);

❌ 痛点2:多外设抢通道导致传输失败?

  • 分析各外设带宽需求,合理分配控制器
  • 高频ADC → DMA2
  • UART通信 → DMA1
  • 使用不同DMA控制器避免总线竞争

❌ 痴点3:想要换个通道却发现映射不支持?

  • 升级选型:选用支持DMAMUX的型号(如STM32H7、G0、L5)
  • 利用灵活路由摆脱束缚

结语:DMA不是辅助功能,而是系统架构的核心拼图

很多工程师把DMA当成“优化技巧”——等主逻辑写完再说。但实际上,合理的DMA规划应该从系统设计之初就开始考虑

当你决定要用ADC做高速采样、要用UART传大量日志、要用SPI驱动LCD屏幕时,就应该同步思考:
- 走哪条DMA通道?
- 是否与其他外设冲突?
- 缓冲区多大合适?
- 是否需要双缓冲或DMA链式传输?

掌握DMA请求映射机制,不只是为了少写几个中断函数,更是为了构建一个低延迟、高吞吐、低功耗的专业级嵌入式系统。

下次你再面对一堆外设并发传输的需求时,不妨问问自己:
“我能把这个任务交给DMA吗?”

如果答案是肯定的,那就放手让它去跑吧——让你的CPU去休息,也让系统真正“智能”起来。

💬 如果你在实际项目中遇到DMA配置难题,欢迎留言讨论。我们一起拆解手册、定位问题,把每一根“数据高速公路”都修得又快又稳。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/10 6:27:41

STM32固件库配置LED灯亮灭操作指南

从点亮第一盏灯开始&#xff1a;深入理解STM32 GPIO控制与固件库实战你有没有过这样的经历&#xff1f;手握一块崭新的STM32开发板&#xff0c;烧录完代码后却不见板载LED闪烁——明明代码看起来没问题&#xff0c;为什么灯就是不亮&#xff1f;别急&#xff0c;这几乎是每个嵌…

作者头像 李华
网站建设 2026/5/3 4:18:59

自然语言分割万物|基于SAM3大模型镜像快速实践

自然语言分割万物&#xff5c;基于SAM3大模型镜像快速实践 1. 引言&#xff1a;从交互式分割到概念提示分割的演进 图像分割作为计算机视觉的核心任务之一&#xff0c;长期以来依赖于精确的几何输入&#xff08;如点击、框选&#xff09;或大量标注数据进行训练。然而&#x…

作者头像 李华
网站建设 2026/5/5 22:09:20

5分钟玩转Cute_Animal_For_Kids_Qwen_Image:儿童可爱动物图片一键生成

5分钟玩转Cute_Animal_For_Kids_Qwen_Image&#xff1a;儿童可爱动物图片一键生成 1. 引言 1.1 儿童内容创作的新需求 在数字教育和亲子互动日益普及的今天&#xff0c;高质量、安全且富有童趣的视觉内容成为家长和教育工作者的核心需求。传统的图像素材库虽然丰富&#xff…

作者头像 李华
网站建设 2026/5/6 9:26:01

Qwen3-Embedding-4B性能调优:GPU利用率提升实战手册

Qwen3-Embedding-4B性能调优&#xff1a;GPU利用率提升实战手册 1. 背景与挑战&#xff1a;向量服务部署中的性能瓶颈 随着大模型在检索增强生成&#xff08;RAG&#xff09;、语义搜索和多模态理解等场景的广泛应用&#xff0c;高效稳定的文本嵌入服务成为系统性能的关键环节…

作者头像 李华
网站建设 2026/5/9 19:40:40

IndexTTS-2-LLM RESTful API对接指南:开发实战教程

IndexTTS-2-LLM RESTful API对接指南&#xff1a;开发实战教程 1. 引言 1.1 学习目标 本文旨在为开发者提供一份完整的 IndexTTS-2-LLM 模型 RESTful API 接入实战教程。通过本教程&#xff0c;您将掌握&#xff1a; 如何调用 IndexTTS-2-LLM 提供的语音合成接口构建 HTTP …

作者头像 李华
网站建设 2026/5/2 8:46:58

Citra模拟器零基础入门:5分钟实现电脑畅玩3DS游戏

Citra模拟器零基础入门&#xff1a;5分钟实现电脑畅玩3DS游戏 【免费下载链接】citra 项目地址: https://gitcode.com/GitHub_Trending/ci/citra 还在为无法重温任天堂3DS经典游戏而烦恼吗&#xff1f;Citra模拟器为你打开了一扇通往怀旧游戏世界的大门。这款强大的开源…

作者头像 李华