1. DMA 基础概念:什么是 DMA、DMA 与 CPU 的数据搬运对比、DMA 在单片机中的作用

各位同学,咱们今天正式开讲 DMA。说实话,我刚开始做嵌入式那会儿,对 DMA 的理解就是「一个能自己搬数据的东西」。但真正用起来才发现,这里面的门道比想象中多得多。咱们今天就把 DMA 的底裤扒干净,从最基础的概念讲起。

1.1 什么是 DMA?

DMA,全称 Direct Memory Access,直接存储器访问。说白了,就是硬件自带的一个「数据搬运工」。它不需要 CPU 插手,自己就能把数据从 A 点搬到 B 点。

我习惯这么跟新人解释:DMA 就是一个专门干苦力活的硬件模块。CPU 是老板,DMA 是搬砖工。老板只需要告诉搬砖工「把这块砖从仓库搬到工地」,搬砖工自己就干完了,老板可以继续算账、开会、写代码。

核心定义:DMA 是一种允许外设与存储器之间、或存储器与存储器之间直接传输数据的硬件机制,传输过程不需要 CPU 参与。

你想想看,如果没有 DMA,CPU 就得亲自干这个活——从外设读一个字节,存到内存,再读下一个字节,再存……这得多浪费?CPU 可是用来跑算法、做决策的,不是用来当搬运工的。

1.2 DMA 与 CPU 的数据搬运对比

咱们直接上表格,一目了然:

对比项 CPU 搬运 DMA 搬运
搬运方式 逐字节/逐字读取→写入 硬件自动批量传输
CPU 占用 100% 占用,无法做其他事 仅初始化时占用,传输过程释放
传输速度 受限于 CPU 主频和指令周期 接近总线极限速度
适用场景 小数据量、实时性要求不高的场合 大数据量、高速传输、实时性要求高的场合
代码复杂度 简单,直接读写寄存器 需要配置 DMA 控制器,稍复杂
功耗 CPU 全速运行,功耗高 CPU 可进入低功耗模式,整体功耗低

我记得有一次做项目,用 STM32F4 采集 ADC 数据,每秒要采 100k 个点。一开始我用 CPU 轮询读取,结果 CPU 占用率直接飙到 85%,系统其他任务全卡死了。后来换成 DMA,CPU 占用率降到 5% 以下,还能顺便跑个 FFT 算法。这就是差距。

我的经验:判断要不要用 DMA,就看两个指标——数据量是否大于 100 字节,或者传输频率是否高于 1kHz。只要满足一个,就优先考虑 DMA。

1.3 DMA 在单片机中的作用

DMA 在单片机里到底能干啥?我总结了四个核心作用:

  1. 解放 CPU——让 CPU 从繁琐的数据搬运中解脱出来,专心做计算和控制。
  2. 提高传输速度——DMA 的传输速度接近总线带宽,比 CPU 逐字节搬运快得多。
  3. 降低系统功耗——DMA 传输时 CPU 可以休眠或降频,特别适合电池供电设备。
  4. 实现后台传输——DMA 可以在后台持续搬运数据,CPU 同时处理其他任务,实现真正的并行。

具体到实际应用,我列几个常见场景:

  • ADC 数据采集:连续采集多通道模拟信号,DMA 自动将结果存入内存缓冲区。
  • DAC 波形输出:DMA 从内存读取波形数据表,自动送给 DAC 生成模拟信号。
  • SPI/I2C 通信:DMA 自动收发数据包,CPU 只在完成时处理一次中断。
  • UART 串口收发:DMA 处理大数据量的串口通信,比如蓝牙模块的数据透传。
  • 存储器拷贝:内存到内存的 DMA 传输,用于快速复制大数组或缓冲区。
  • 显示刷新:LCD/OLED 的显存刷新,DMA 自动将图像数据送到显示接口。

避坑指南:我曾经在一个项目中,用 DMA 做 SPI 通信,结果发现数据总是错位。查了两天才找到原因——DMA 的传输宽度和外设的数据宽度不匹配。SPI 是 8 位,DMA 配置成了 16 位,结果高低字节全乱了。所以配置 DMA 时,传输宽度一定要和外设寄存器宽度一致。

1.4 DMA 的工作流程

咱们用一张图来理解 DMA 的完整工作流程:

DMA 工作流程图 CPU 配置 DMA DMA 等待触发信号 外设请求触发 DMA DMA 开始传输数据 传输完成 → 触发中断 CPU 处理缓冲区数据 循环传输 / 结束 关键点 DMA 传输期间 CPU 完全空闲 仅在完成时通过中断通知 CPU

流程其实很简单:CPU 先配置好 DMA 的源地址、目标地址、传输长度、触发源等参数,然后 DMA 就等着。外设一发出请求,DMA 立刻开始搬数据。搬完了,触发一个中断告诉 CPU「活干完了」。CPU 这时候再去处理缓冲区里的数据。

记住这个原则:DMA 负责「搬」,CPU 负责「算」。各司其职,互不干扰。

1.5 DMA 的三种传输模式

不同单片机的 DMA 模式略有差异,但主流的有三种:

传输模式 描述 典型应用
外设→内存 从外设数据寄存器读取数据,存入内存缓冲区 ADC 采集、UART 接收、SPI 接收
内存→外设 从内存读取数据,写入外设数据寄存器 DAC 输出、UART 发送、SPI 发送
内存→内存 从一个内存地址拷贝数据到另一个内存地址 数据缓冲区拷贝、图像数据搬运

嗯,这里要注意:内存到内存的传输,有些低端单片机不支持。比如早期的 STM32F1 系列,DMA 只能在外设和内存之间传,不能内存到内存。选型的时候一定要看数据手册。

1.6 本章小结

咱们今天把 DMA 的基础概念捋了一遍。说白了,DMA 就是一个硬件级的 DMA 控制器,专门负责数据搬运,让 CPU 腾出手来做更重要的事。它的核心价值就三个字:快、省、稳——速度快、省 CPU、传输稳定。