13-HAL库DMA系统总结

1.间接

DMA:Direct Memory Access,直接存储访问,实现数据在外设与存储器或存储器之间高速访问,数据移动过程无需CPU操作控制,因此可以大大解放CPU负担。

外设(ADC、SPI、I2C、DCMI等外设的数据寄存器),存储器(片内SRAM、外部存储器、片内Flash等等)。外设到存储器,例如将AD转换的数据转移到所定义的存储区中。存储器到外设多用于外设的发送通信,例如串口不定长数据的输入输出。

STM32F7xx系列有2个DMA控制器,每个控制器具有8个数据流(stream),每个数据流有8个通道(channel),对应如下:

每个外设请求占用一个数据流通道,相同外设请求可以占用不同数据流通道。数据流的传输依靠仲裁器进行管理和判断,包括软件(例如初始化中mydma2.Init.Priority=DMA_PRIORITY_MEDIUM)和硬件(数据流编号越低,优先权越高)。DMA传输有FIFO模式和直接模式,直接模式在每个外设请求时立即启动对存储器传输,FIFO模式为源数据传输到目标地址前将数据临时存放在FIFO(先进先出存储器缓冲区)中。FIFO模式对于要求源地址和目标地址数据宽度不同时很有用,同时可用于突发传输。

DMA2的存储器端口和外设端口都连接到AHB,但DMA的存储区端口没有AHB2外设的访问权,同时外设端口只连接到APB1外设,所以DMA1不能实现存储器到存储器传输。

2.DMA相关函数解析

关于DMA,ST官方提供了HAL库(封装函数)和LL库(直接操作寄存器)。和GPIO定义类似,需要先使能相关时钟,定义句柄结构体DMA_HandleTypeDef mydma2,随后进行DMA的各项配置,最后进行初始化。

typedef struct __DMA_HandleTypeDef
{
    DMA_Stream_TypeDef          *Instance;                                                    
    DMA_InitTypeDef              Init;                                                         
    HAL_LockTypeDef              Lock;                                                         
    __IO HAL_DMA_StateTypeDef    State; 
    void                        *Parent;
    void                   (* XferCpltCallback)( struct __DMA_HandleTypeDef * hdma); 
    void                   (* XferHalfCpltCallback)( struct __DMA_HandleTypeDef * hdma);
    void                   (* XferM1CpltCallback)( struct __DMA_HandleTypeDef * hdma); 
    void                   (* XferM1HalfCpltCallback)( struct __DMA_HandleTypeDef * hdma); 
    void                   (* XferErrorCallback)( struct __DMA_HandleTypeDef * hdma);  
    void                   (* XferAbortCallback)( struct __DMA_HandleTypeDef * hdma); 
    __IO uint32_t                ErrorCode; 
    uint32_t                     StreamBaseAddress; 
    uint32_t                     StreamIndex; 
}DMA_HandleTypeDef;
typedef struct
{
   uint32_t     Channel;               //通道
   uint32_t     Direction;             //方向
   uint32_t     PeriphInc;             //外设递增
   uint32_t     MemInc;                //内存递增
   uint32_t     PeriphDataAlignment;   //外设数据宽度
   uint32_t     MemDataAlignment;      //内存数据宽度
   uint32_t     Mode;                  //模式选择
   uint32_t     Priority;              //优先级
   uint32_t     FIFOMode;              //FIFO模式
   uint32_t     FIFOThreshold;         //FIFO阈值
   uint32_t     MemBurst;              //内存突发传输
   uint32_t     PeriphBurst;           //外设突发传输
}DMA_InitTypeDef;

3.DMA初始化及配置

HAL库中,基本上都是结合XXX_HandleTypeDef 结构体和XXX_InitTypeDef 结构体进行初始化配置。

#include "dma.h"
#include "stm32f7xx_hal.h"

uint32_t DMA_Result;
DMA_HandleTypeDef Mydma1;

void MyDMA_Config(void){
	
	__HAL_RCC_DMA2_CLK_ENABLE();    //时钟使能
	
	Mydma1.Instance=DMA2_Stream0;       //数据流
	Mydma1.Init.Channel=DMA_CHANNEL_0;   //通道
	Mydma1.Init.Direction=DMA_PERIPH_TO_MEMORY;    //传输方向
	Mydma1.Init.PeriphInc=DMA_PINC_DISABLE;  //外设是否递增
	Mydma1.Init.MemInc=DMA_MINC_DISABLE;    //内存是否递增
	Mydma1.Init.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD;   //外设数据宽度半个字节
	Mydma1.Init.MemDataAlignment=DMA_MDATAALIGN_HALFWORD;   //内存数据宽度半个字节
	Mydma1.Init.Mode=DMA_CIRCULAR;    //循环模式
	Mydma1.Init.Priority=DMA_PRIORITY_MEDIUM;   //优先级中等
	Mydma1.Init.FIFOMode=DMA_FIFOMODE_DISABLE;  //是否使能FIFO模式
	Mydma1.Init.PeriphBurst=DMA_PBURST_SINGLE;  //外设突发传输
	Mydma1.Init.MemBurst=DMA_MBURST_SINGLE;     //内存突发传输
	
	HAL_DMA_Init(&Mydma1);    //初始化
	HAL_DMA_Start(&Mydma1,ADC1_BASE,DMA_Result,2400);   //启动DMA
}

随后还需进行相关外设的配置:如串口,AD采样等。

4.DMA中断

中断配置,中断函数调用,回调函数覆盖。

猜你喜欢

转载自blog.csdn.net/weixin_42480952/article/details/83117524