1. DMA基础概念:什么是DMA、DMA与CPU数据搬运的区别、DMA在嵌入式系统中的作用
各位同学,咱们今天聊聊DMA。说实话,我刚入行那会儿,觉得DMA就是个“数据搬运工”,没啥了不起的。直到有一次做高速数据采集项目,CPU被中断占得死死的,系统几乎卡死——我才真正意识到,不懂DMA,嵌入式开发就少了一条腿。
1.1 什么是DMA
DMA,全称Direct Memory Access,直接存储器访问。说白了,就是硬件自己搬数据,不用CPU插手。
我习惯这么理解:DMA是一个专门干“数据拷贝”的硬件模块。它有自己的地址总线和控制逻辑,能在内存和外设之间、内存和内存之间,自动完成数据传输。
核心定义:DMA是一种允许外设或内存直接交换数据,而不需要CPU逐字节参与的硬件机制。
举个例子,ADC采样了1024个点,传统做法是CPU每次读一个数,存到数组里。有了DMA,你只需要告诉它:“从ADC数据寄存器搬1024个数到内存地址0x20001000”,然后它自己干完,最后给你发个中断说“搞定了”。
1.2 DMA与CPU数据搬运的区别
这个对比很关键。我见过不少工程师,觉得DMA可有可无,反正CPU也能搬。嗯,咱们看看区别:
| 对比项 | CPU搬运 | DMA搬运 |
|---|---|---|
| 执行方式 | 逐条指令执行,每次搬一个字节/字 | 硬件自动完成,一次可搬整个数据块 |
| CPU占用 | 全程占用CPU,无法做其他事 | 仅初始化时占用,传输过程CPU可干别的 |
| 传输速度 | 受限于指令执行速度,通常较慢 | 接近总线带宽,速度远快于CPU |
| 适用场景 | 小数据量、非实时、简单控制 | 大数据量、高速、实时性要求高 |
| 功耗 | CPU全速运行,功耗较高 | DMA模块功耗远低于CPU |
| 编程复杂度 | 简单,直接读写寄存器 | 需要配置DMA控制器,稍复杂 |
你想想看,CPU搬数据就像你亲自去仓库搬箱子,搬一箱就少一箱的精力。DMA呢,就像雇了个搬运工,你只需要告诉他“搬到哪儿”,然后自己可以去写代码、做算法、处理逻辑。
我的经验:在STM32F4上做过测试,CPU用循环搬1024个16位数据大约需要50μs,而DMA只需要不到5μs。10倍的差距,在高频采样场景下就是能不能跑得动的区别。
1.3 DMA在嵌入式系统中的作用
DMA的作用,我总结为三个核心价值:
- 解放CPU:让CPU从繁琐的数据搬运中解脱出来,专注于控制、计算和协议处理
- 提升吞吐量:数据搬运速度接近总线极限,适合高速外设(ADC、DAC、摄像头、以太网)
- 降低延迟:DMA传输的启动延迟远小于中断响应延迟,适合实时性要求高的场景
我曾经做一个多通道音频采集项目,8路麦克风同时采样,每路48kHz、16位数据。如果用中断方式,CPU几乎100%在响应中断,连滤波算法都跑不动。换成DMA后,CPU占用率降到15%左右,还能同时做FFT和音频编码。
避坑指南:DMA不是万能的。小数据量(比如几个字节)用DMA反而更慢,因为配置DMA通道的开销比CPU直接搬还大。我一般以64字节为分界线,小于这个数就让CPU搬。
下面这张图,是我画的一个DMA工作流程,帮你直观理解:
1.4 DMA的典型应用场景
在实际项目中,DMA最常见的几个用武之地:
- ADC连续采样:配置DMA自动将ADC转换结果搬入缓冲区,CPU定期处理
- DAC波形输出:DMA从波形表搬数据到DAC,实现无CPU干预的连续波形输出
- SPI/I2C通信:大数据包收发时,DMA自动处理,CPU只负责协议解析
- 内存拷贝:比如从摄像头缓冲区搬到显示缓冲区,DMA比memcpy快得多
- 定时器触发传输:结合定时器,实现精确周期的数据传输
一句话总结:DMA就是嵌入式系统的“硬件搬运工”,让CPU从苦力活中解放出来,去做更有价值的事。