DMA的作用形同CPU请了一个搬运工,搬运工负责部分数据的单独处理,CPU可以同时处理其他事件。
1.DMA 负责数据的搬运,所以必须要有三个基本要素:数据源,数据目的,数据长度。
2.而DMA一般处理 内存和外设,内存和内存之间的事件。因此还需要配置双方的属性,即外设,内存,和数据方向。
3.1个DMA通常有多个通道,而处理单一事件只需占用一个通道,所以还需要选择通道。如果有多个通道在工作,还要设置通道优先级。
4.DMA负责双方的数据传输,还必须知道双方的起始存放地址,以及每次取数据的宽度,和数据在存储区的增长方式。
5.DMA是一次执行,还是循环执行。
以stm32的AD采集为例:DMA的三要素配置如下:
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(DMA1_Channel1);//初始化通道一为默认值, AD1 使用DMA通道1
DMA_InitStructure.DMA_PeripheralBaseAddr=(u32)&ADC1->DR;//数据源
DMA_InitStructure.DMA_MemoryBaseAddr=(u32)AD_Value;//目的
DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC;//外设作为数据来源
DMA_InitStructure.DMA_BufferSize=M*N;//DMA缓存大小
DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//外设地址寄存器不变
DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;//内存寄存器地址递增
DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;//外设数据源宽度为16位
DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;//内存数据目的宽度 16位
// DMA_InitStructure.DMA_Mode=DMA_Mode_Circular;//工作循环存储模式
DMA_InitStructure.DMA_Mode=DMA_Mode_Normal;//工作正常模式,只执行一次
DMA_InitStructure.DMA_Priority=DMA_Priority_High;//此DMA通道为高优先级
DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;//DMA禁止内存到内存传输
DMA_Init(DMA1_Channel1,&DMA_InitStructure);
// DMA_Cmd(DMA1_Channel1,ENABLE);//启动DMA
}
总结:
1.DMA_BufferSize决定了一次DMA传输的数据长度
2.DMA启动后,可以读DMA的CNDYR寄存器了解还剩多少数据
3.如果执行模式为DMA_Mode_Normal,DMA把DMA_BufferSize长度的数据传完后就会设置一个传输完成标志位DMA1_FLAG_TC1
4.如果执行模式为DMA_Mode_Circular,每次传输完DMA_BufferSize都会设置DMA1_FLAG_TC1
5.CPU和DMA不能同时访问同一个外设,例如,使用DMA方式往串口1发送数据,在DMA还没有发送完时,CPU如果也要往串口1发送数据,此时CPU会阻塞,直到DMA把串口1数据发送完为止,CPU才能访问串口1。