DMA 传输方式无需 CPU 直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为 RAM 与 I/O 设备开辟一条直接传送数据的通路,能使 CPU 的效率大为提高。
源和目标地址:
仲裁器:为两个AHB主端口(存储器和外设端口)提供基于请求优先级的8个DMA数据流请求管理,并启动外设/存储器访问序列
DMA配置过程(串口发送DMA)
1)使能 DMA2 时钟,并等待数据流可配置。
库函数使能 DMA2 时钟的方法为:
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2 时钟使能
等待 DMA 可配置,也就是等待 DMA_SxCR 寄存器最低位为 0 的方法为:
while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){
}//等待 DMA 可配置
void DMA_Init(DMA_Stream_TypeDef* DMAy_Streamx, DMA_InitTypeDef* DMA_InitStruct);
进入DMA结构体指针,找到参数的有效值进行配置。
3)使能串口 1 的 DMA 发送
进行 DMA 配置之后,我们就要开启串口的 DMA 发送功能,使用的函数是:
USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE); //使能串口 1 的 DMA 发送
4)使能 DMA2 数据流 7,启动传输。
使能 DMA 数据流的函数为:
void DMA_Cmd(DMA_Stream_TypeDef* DMAy_Streamx, FunctionalState NewState)
使能 DMA2_Stream7,启动传输的方法为:
DMA_Cmd (DMA2_Stream7,ENABLE);
通过以上 4 步设置,我们就可以启动一次 USART1 的 DMA 传输了。
5)查询 DMA 传输状态 在 DMA 传输过程中,我们要查询 DMA 传输通道的状态,使用的函数是:
FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG)
比如我们要查询 DMA 数据流 7 传输是否完成,方法是:
DMA_GetFlagStatus(DMA2_Stream7,DMA_FLAG_TCIF7);
这里还有一个比较重要的函数就是获取当前剩余数据量大小的函数:
uint16_t DMA_GetCurrDataCounter(DMA_Stream_TypeDef* DMAy_Streamx);
比如我们要获取 DMA 数据流 7 还有多少个数据没有传输,方法是:
DMA_GetCurrDataCounter(DMA1_Channel4);
同样,我们也可以设置对应的 DMA 数据流传输的数据量大小,函数为:
void DMA_SetCurrDataCounter(DMA_Stream_TypeDef* DMAy_Streamx, uint16_t Counter);