一、什么是DMA?
DMA,全称为: Direct Memory Access,即直接存储器访问。 DMA 传输方式无需 CPU 直接
控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为 RAM 与 I/O 设备
开辟一条直接传送数据的通路, 能使 CPU 的效率大为提高。
STM32F4 最多有 2 个 DMA 控制器(DMA1 和 DMA2), 共 16 个数据流(每个控制器 8个), 每一个 DMA 控制器都用于管理一个或多个外设的存储器访问请求。每个数据流总共可以有多达 8个通道(或称请求)。每个数据流通道都有一个仲裁器,用于处理 DMA 请求间的优先级。
即:DMA是一个协助CPU搬运数据的助手,可以大大减小CPU在搬运数据工作的工作量
DMA 控制器执行直接存储器传输:因为采用 AHB 主总线,它可以控制 AHB 总线矩阵来
启动 AHB 事务。它可以执行下列事务:
1, 外设到存储器的传输
3, 存储器到外设的传输
3, 存储器到存储器的传输
这里特别注意一下,存储器到存储器需要外设接口可以访问存储器,而仅 DMA2 的外设接口可以访问存储器,所以仅 DMA2 控制器支持存储器到存储器的传输, DMA1 不支持。
二、DMA如何使用?
1)使能 DMA2 时钟,并等待数据流可配置。
DMA 的时钟使能是通过 AHB1ENR 寄存器来控制的,这里我们要先使能时钟,才可以配置 DMA
相关寄存器。 HAL 库方法为:
__HAL_RCC_DMA2_CLK_ENABLE();//DMA2 时钟使能
__HAL_RCC_DMA1_CLK_ENABLE();//DMA1 时钟使能
2) 初始化 DMA2 数据流7 ,包括配置通道,外设地址,存储器地址,传输数据量等。
DMA 的某个数据流各种配置参数初始化是通过 HAL_DMA_Init 函数实现的,该函数声明为:
HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma);
该函数只有一个 DMA_HandleTypeDef 结构体指针类型入口参数,结构体定义为:
typedef struct __DMA_HandleTypeDef
{
DMA_Stream_TypeDef *Instance; /*!< Register base address */
DMA_InitTypeDef Init; /*!< DMA communication parameters */
HAL_LockTypeDef Lock; /*!< DMA locking object */
__IO HAL_DMA_StateTypeDef State; /*!< DMA transfer state */
void *Parent; /*!< Parent object state */
void (* XferCpltCallback)( struct __DMA_HandleTypeDef * hdma); /*!< DMA transfer complete callback */
void (* XferHalfCpltCallback)( struct __DMA_HandleTypeDef * hdma); /*!< DMA Half transfer complete callback */
void (* XferM1CpltCallback)( struct __DMA_HandleTypeDef * hdma); /*!< DMA transfer complete Memory1 callback */
void (* XferM1HalfCpltCallback)( struct __DMA_HandleTypeDef * hdma); /*!< DMA transfer Half complete Memory1 callback */
void (* XferErrorCallback)( struct __DMA_HandleTypeDef * hdma); /*!< DMA transfer error callback */
void (* XferAbortCallback)( struct __DMA_HandleT