DMA比较好用,也比较简单,今天在做多通道ADC“连续”“扫描”采样时,对DMA有了更深一点的认识,今天给大家分享下:

#define ADC1_DR_Address    ((uint32_t)0x4001244C)

unsigned short Buff[3];  

......

 DMA_DeInit(DMA1_Channel1);  
 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address;  
 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Buff;  
 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  
 DMA_InitStructure.DMA_BufferSize = 3;  
 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  
 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  
 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;  
 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;  
*** DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;***
 DMA_InitStructure.DMA_Priority = DMA_Priority_High;  
**DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;**
 DMA_Init(DMA1_Channel1, &DMA_InitStructure);  
 DMA_Cmd(DMA1_Channel1, ENABLE);  

初始化时,要先用DMA_DeInit将DMA的通道初始化成缺省值。

外设地址设置,内存基地址设置,设置外设的传输属性(输入/输出),这些都容易理解;

 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  

#define DMA_DIR_PeripheralDST              ((uint32_t)0x00000010)  

#define DMA_DIR_PeripheralSRC              ((uint32_t)0x00000000)

这里是设置谁为数据传输源;

DMA_InitStructure.DMA_BufferSize = 3;

如果是获取一组数值,像ADC,USART,我们可以用一个缓冲区,如果不用,像ADC数据更新快的,马上就被刷新了。我这里的DMA_Buffersize 是 Buff的大小;


DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  

#define DMA_PeripheralInc_Enable           ((uint32_t)0x00000040)  
#define DMA_PeripheralInc_Disable          ((uint32_t)0x00000000)  

#define DMA_MemoryInc_Enable               ((uint32_t)0x00000080)  
#define DMA_MemoryInc_Disable              ((uint32_t)0x00000000)  

这个根据需要进行设置;

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;  
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;  

#define DMA_PeripheralDataSize_Byte        ((uint32_t)0x00000000)  
#define DMA_PeripheralDataSize_HalfWord    ((uint32_t)0x00000100)  
#define DMA_PeripheralDataSize_Word        ((uint32_t)0x00000200)  

#define DMA_MemoryDataSize_Byte            ((uint32_t)0x00000000)  
#define DMA_MemoryDataSize_HalfWord        ((uint32_t)0x00000400)  
#define DMA_MemoryDataSize_Word            ((uint32_t)0x00000800)  

这个设置获取数据的大小;


*DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;*  

#define DMA_Mode_Circular                  ((uint32_t)0x00000020)  
#define DMA_Mode_Normal                    ((uint32_t)0x00000000)  

这个要强调下,像我这里,要不断更新Buff[0],Buff[1],Buff[2],我上面设置的缓冲区正好也是3,我们可以用Circular属性来设置!他就不停的刷新这段地址!

他还有一种属性是Normal,这种属性一般用在Point 2 Point时使用;

DMA_InitStructure.DMA_Priority = DMA_Priority_High;  

#define DMA_Priority_VeryHigh              ((uint32_t)0x00003000)  
#define DMA_Priority_High                  ((uint32_t)0x00002000)  
#define DMA_Priority_Medium                ((uint32_t)0x00001000)  
#define DMA_Priority_Low                   ((uint32_t)0x00000000)  

因为DMA有多路,所以我们要规定先传哪路数据,所以我们就要规定一个优先级;

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  

#define DMA_M2M_Enable                     ((uint32_t)0x00004000)  
#define DMA_M2M_Disable                    ((uint32_t)0x00000000)  

这个是设置是不是Memary to Memary的!