一、DMA概述
DMA,全称为: Direct Memory Access,即直接存储器访问。 DMA 传输方式无需 CPU 直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为 RAM 与 I/O 设备开辟一条直接传送数据的通路, 能使 CPU 的效率大为提高。
注意:DMA其实就是给CPU打工的搬运工,减轻CPU的工作负担。
二、STM32F4DMA的特点
STM32F4 最多有 2 个 DMA 控制器(DMA1 和 DMA2), 共 16 个数据流(每个控制器 8 个), 每一个 DMA 控制器都用于管理一个或多个外设的存储器访问请求。每个数据流总共可以有多达 8个通道(或称请求)。每个数据流通道都有一个仲裁器,用于处理 DMA 请求间的优先级。
三、STM32F4 DMA
3.1 STM32F4 DMA的框架
STM32F4 有两个 DMA 控制器, DMA1 和 DMA2
DMA 控制器执行直接存储器传输:因为采用 AHB 主总线,它可以控制 AHB 总线矩阵来启
动 AHB 事务。
它可以执行下列事务:
● 外设到存储器的传输 ✔
● 存储器到外设的传输 ✔
● 存储器到存储器的传输
外设:USART ADC(数模转换器) IIC SPI.....
DMA 控制器提供两个 AHB 主端口: AHB 存储器端口(用于连接存储器)和 AHB 外设端口
(用于连接外设)。
但是,要执行存储器到存储器的传输, AHB 外设端口必须也能访问存储器。
3.2 STM32F4DMA的通道
每个数据流都与一个 DMA 请求相关联,此 DMA 请求可以从 8 个可能的通道请求中选出。此选择由 DMA_SxCR 寄存器中的 CHSEL[2:0] 位控制。
DMA映射表如下
不同的STM32单片机型号,这个映射表是不一样的。
编程时,一定要对照上面的图,找到外设对应的哪个DMA,哪个通道,哪个数据流
外设串口1发送数据:USART1_TX, 根据上图,找到外设串口1发送数据:USART1_TX,对应的关系如下
DMA2 -- 通道4 -- 数据流7
3.3 DMA数据流
8 个 DMA 控制器数据流都能够提供源和目标之间的单向传输链路。
每个数据流配置后都可以执行:
● 常规类型事务:
存储器到外设(这种是最简单,也是最好理解的)
外设到存储器
存储器到存储器的传输。
● 双缓冲区类型事务:使用存储器的两个存储器指针的双缓冲区传输(当 DMA 正在进行自/至缓冲区的读/写操作时,应用程序可以进行至/自其它缓冲区的写/读操作)。
要传输的数据量(多达 65535)可以编程,并与连接到外设 AHB 端口的外设(请求 DMA 传输)的源宽度相关。每个事务完成后,包含要传输的数据项总量的寄存器都会递减。这个理解为设置传输量,每传输一个,数据量少1
3.4 源、目标和传输模式
源传输和目标传输在整个 4 GB 区域(地址在 0x0000 0000 和 0xFFFF FFFF 之间)都可以寻址外设和存储器。
传输方向使用 DMA_SxCR 寄存器中的 DIR[1:0] 位进行配置,有三种可能的传输方向:存储器到外设、外设到存储器或存储器到存储器。 表 37 介绍了相应的源和目标地址。
3.5 仲裁器
仲裁器为两个 AHB 主端口(存储器和外设端口)提供基于请求优先级的 8 个 DMA 数据流请
求管理,并启动外设/存储器访问序列。
优先级管理分为两个阶段:
● 软件:每个数据流优先级都可以在 DMA_SxCR 寄存器中配置。分为四个级别:
— 非常高优先级
— 高优先级
— 中优先级
— 低优先级
● 硬件:指的是数据流0、数据流1...数据流7, 编号低优先级越高。
如果两个请求具有相同的软件优先级,则编号低的数据流优先于编号高的数据
流。例如,数据流 2 的优先级高于数据流 4。
3.6DMA中断
对于每个 DMA 数据流,可在发生以下事件时产生中断:
● 达到半传输
● 传输完成
● 传输错误
● FIFO上溢/下溢
● 直接模式错误
可以使用单独的中断使能位以实现灵活性,如表 43 所示。
四、DMA案例
DMA配置程序过程(串口1发送运行内存RAM的数据)
存储器到外设
配置串口发送运行内存RAM的数据前提是配置好串口发送数据代码
DMA2 -- 数据流7 -- 通道4
1、 使能DMA时钟
RCC_AHB1PeriphClockCmd();
2、复位DMA寄存器
DMA_DeInit(DMA_Streamx);
3、初始化DMA通道参数
DMA_Init();
4、使能DMA1通道,启动传输。
DMA_Cmd();
5、配置NVIC,传输完成中断
DMA_ITConfig(DMA_Streamx, DMA_IT_TC, ENABLE);
6、使能串口DMA发送,串口DMA使能函数://串口与DMA联动,启动传输
USART_DMACmd();
其它函数
查询DMA的EN位,确保数据流就绪,可以配置
DMA_GetCmdStatus();
设置通道当前剩余数据量
DMA_SetCurrDataCounter();
查询DMA传输状态
DMA_GetFlagStatus();
获取/设置通道当前剩余数据量:
DMA_GetCurrDataCounter();
例子源码(内存到外设):