STM32F4-DMA及相关配置

参考资料:

1、正点原子探索者STM32f407开发板-《STM32f407开发指南-库函数版本》-第28章DMA实验;

2、STM32F4xx 官方参考资料《STM32F4xx中文参考手册》-第9章-DMA控制器。

目录

概念认知:

DMA是什么?

通道选择:

DMA请求映射:

DMA事务:

三种传输方式原理:

DMA_SxCR寄存器(x=0~7):

其他

编辑数据宽度、封装/解封、字节序

双缓冲区模式

DMA 中断

流配置过程(重要):

DMA配置参数

重要函数:

DMA_Init();

DMA配置程序过程(串口发送DMA)


概念认知:

DMA是什么?

全称Direct Memory Access,即直接存储器访问。

正常情况下,数据如果想要传输,得由CPU先读取目标数据,再传向目标地址。有了DMA后,传输的事就是DMA做的了,CPU只要初始化DMA就可以了。

DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场过程,通过硬件为RAMIO设备开辟一条直接传输数据的通道,使得CPU的效率大大提高。

作用:为CPU减负。

STM32F4最多有2DMA控制器,2DMA控制器总共有16个数据流(每个控制器8个),8个数据流中每一个都连接到专用硬件DMA通道(请求)。每个DMA控制器都用于管理一个或者多个外设的存储器访问请求。每个数据流总共可以有多达8个通道(或请求)(理论上一共就是16x8=128个通道,实际上每个通道都固定了对应的映射,所以并没有128个),每个通道都有一个仲裁器,用于处理DMA请求间的优先级。

注:每个数据流只能同时接一个通道!

STM32F4-DMA及相关配置_第1张图片

DMA传输,由源地址->目标地址,源地址和目标地址都可以是外设、存储器的地址。

特别的,当存储器存储器时候,仅限于DMA2控制器;一般没有外设外设

可设置独立的源和目标传输宽度(字节(8位)、半字(16位)、字(32位)):源和目标的数据宽度不相等时,DMA 自动封装/解封必要的传输数据来优化带宽。这个特性仅在 FIFO 模式下可用。如:A设置8位传输出去,B设置32位接收,FIFO会等A传出4次,共32位数据,然后封装成B的一次“字”的接收。

通道选择:

STM32F4-DMA及相关配置_第2张图片

DMA请求映射:

STM32F4-DMA及相关配置_第3张图片

 STM32F4-DMA及相关配置_第4张图片

DMA事务:

STM32F4-DMA及相关配置_第5张图片

 一般通过DMA_SxCR寄存器DMA_SxM0AR寄存器来控制源到目标的传输类型:

STM32F4-DMA及相关配置_第6张图片

三种传输方式原理:

STM32F4-DMA及相关配置_第7张图片

 STM32F4-DMA及相关配置_第8张图片

 STM32F4-DMA及相关配置_第9张图片

DMA_SxCR寄存器(x=0~7):

STM32F4-DMA及相关配置_第10张图片

STM32F4-DMA及相关配置_第11张图片

其他

关于“指针递增”,“循环模式”之类的,暂时用不到,不多赘述。

编辑数据宽度、封装/解封、字节序

STM32F4-DMA及相关配置_第12张图片

可以看到由DMA_SxNDTR来决定数据宽度,PSIZE就是外设,MSIZE就是储存器。

双缓冲区模式

STM32F4-DMA及相关配置_第13张图片

 STM32F4-DMA及相关配置_第14张图片

也就是说,在开启双缓冲区模式的情况下,DMA_SxM0ARDMA_SxM1AR才会同时有用,一般情况下只有DMA_SxM0AR有效,这些寄存器装的都是地址

简单来说,开启时,一个事务结束后,源地址/目标地址进行切换,所以叫双缓冲,如果是x缓冲,就是x个源地址/目标地址在事务结束后进行切换。

DMA 中断

STM32F4-DMA及相关配置_第15张图片

流配置过程(重要):

STM32F4-DMA及相关配置_第16张图片

 STM32F4-DMA及相关配置_第17张图片

DMA配置参数

通道

优先级

数据传输方向

存储器/外设 数据宽度

存储器/外设 地址是否增量

循环模式

数据传输量

函数在stm32f4xx_dma.c  /  stm32f4xx_dma.h中

常用的DMA库函数

void DMA_Init(DMA_Stream_TypeDef* DMAy_Streamx, DMA_InitTypeDef* DMA_InitStruct);
void DMA_Cmd(DMA_Stream_TypeDef* DMAy_Streamx, FunctionalState NewState);

void DMA_SetCurrDataCounter(DMA_Stream_TypeDef* DMAy_Streamx, uint16_t Counter);
uint16_t DMA_GetCurrDataCounter(DMA_Stream_TypeDef* DMAy_Streamx);

void DMA_DoubleBufferModeConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t Memory1BaseAddr,uint32_t DMA_CurrentMemory);
void DMA_DoubleBufferModeCmd();
void DMA_MemoryTargetConfig(DMA_Stream_TypeDef* DMAy_Streamx, 
                 uint32_t MemoryBaseAddr, uint32_t DMA_MemoryTarget);
uint32_t DMA_GetCurrentMemoryTarget(DMA_Stream_TypeDef* DMAy_Streamx);

FunctionalState DMA_GetCmdStatus(DMA_Stream_TypeDef* DMAy_Streamx);
uint32_t DMA_GetFIFOStatus(DMA_Stream_TypeDef* DMAy_Streamx);
FlagStatus DMA_GetFlagStatus(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_FLAG);
void DMA_ClearFlag(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_FLAG);
void DMA_ITConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT, FunctionalState NewState);
ITStatus DMA_GetITStatus(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT);
void DMA_ClearITPendingBit(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT);
常用的外设 DMA 使能库函数
void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq,
                                                                             FunctionalState NewState);
void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void DAC_DMACmd(uint32_t DAC_Channel, FunctionalState NewState);
void I2C_DMACmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
void SDIO_DMACmd(FunctionalState NewState);
void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq, 
                                                                          FunctionalState NewState);

void TIM_DMAConfig(TIM_TypeDef* TIMx, uint16_t TIM_DMABase, 
                                                                      uint16_t TIM_DMABurstLength)
void TIM_DMACmd(TIM_TypeDef* TIMx, uint16_t TIM_DMASource,
                                                                       FunctionalState NewState);

一般在相应的外设那里有对应的DMA使能函数,如USART:

STM32F4-DMA及相关配置_第18张图片

重要函数:

DMA_Init();

void DMA_Init(DMA_Stream_TypeDef* DMAy_Streamx, DMA_InitTypeDef* DMA_InitStruct);


typedef struct
{
  uint32_t DMA_Channel;           
  uint32_t DMA_PeripheralBaseAddr; 
  uint32_t DMA_Memory0BaseAddr;    
  uint32_t DMA_DIR;              
  uint32_t DMA_BufferSize;     
  uint32_t DMA_PeripheralInc;     
  uint32_t DMA_MemoryInc;          
  uint32_t DMA_PeripheralDataSize; 
  uint32_t DMA_MemoryDataSize;    
  uint32_t DMA_Mode;            
  uint32_t DMA_Priority;         
  uint32_t DMA_FIFOMode;         
  uint32_t DMA_FIFOThreshold;      
  uint32_t DMA_MemoryBurst;       
  uint32_t DMA_PeripheralBurst;   
}DMA_InitTypeDef;

DMA配置程序过程(串口发送DMA)

使能DMA时钟

   RCC_AHB1PeriphClockCmd();

初始化DMA通道参数

   DMA_Init();

使能串口DMA发送,串口DMA使能函数:

  USART_DMACmd();

④查询DMAEN位,确保数据流就绪,可以配置

   DMA_GetCmdStatus();

⑤设置通道当前剩余数据量

   DMA_SetCurrDataCounter();

使能DMA1通道,启动传输。

   DMA_Cmd();

查询DMA传输状态

  DMA_GetFlagStatus();

⑥获取/设置通道当前剩余数据量:

  DMA_GetCurrDataCounter();

Fin.

你可能感兴趣的:(stm32,stm32,单片机,arm)