z755924843的个人空间 https://bbs.21ic.com/?814467 [收藏] [复制] [RSS]

日志

浅谈STM32 DMA

已有 1137 次阅读2013-8-19 14:05 |个人分类:STM32|系统分类:单片机| STM32, DMA

其全称为:direct memory Access ;根据ST公司提供的信息来看,DMA是STM32中一个独立于cortex-M3
内核的模块,有点类似ADC、PWM、TIMER等模块;主要功能是通信的“桥梁”的作用,可以将所有外设映射到寄存器连接起来,这样就可以高速访问各寄存器而不受cpu的支配,传输双向的.

typedef struct
{
    vu32 CCR;
    vu32 CNDTR;
    vu32 CPAR;
    vu32 CMAR;
}DMA_Channle_TypeDef;

  DMA_DeInit(DMA_Channel1);//USART1_RX Channle5 ,USART1_TX Channle4

这句是给DMA配置通道,根据ST提供的资料,STM3210FxDMA包含7CH1~CH7),也就是说可以为外设或memory提供7座“桥梁”(请允许使用桥梁一词,我觉得更容易理解,哈哈,别“拍砖”呀!);

typedef struct

{

uint32_t DMA_PeripheralBaseAddr;//用于设置DMA通道的外设基地址;

uint32_t DMA_MemoryBaseAddr; //用于设置DMA通道存储器基地址,我们自己定义的变量

uint32_t DMA_DIR;  //设置DMA的传输方向“DMA_DIR_PeripheralDST”DMA目的地

                        “DMA_DIR_PeripheralSRC”DMA源

uint32_t DMA_BufferSize; //用于设置DMA通道缓冲区的数据单元大小。

uint32_t DMA_PeripheralInc; //DMA递增模式,如果使用多个DMA,此位应使能

uint32_t DMA_MemoryInc; //

uint32_t DMA_PeripheralDataSize;//

uint32_t DMA_MemoryDataSize;  //  

uint32_t DMA_Mode; //

uint32_t DMA_Priority;//  

uint32_t DMA_M2M;   //

}DMA_InitTypeDef;//


1、  下面代码是一个标准DMA设置,当然实际应用中可根据实际情况进行裁减:

 

  DMA_DeInit(DMA_Channel1);

  上面这句是给DMA配置通道,根据ST提供的资料,STM3210Fx中DMA包含7个通道(CH1~CH7),也就是说可以为外设或memory提供7座“桥梁”(请允许我使用桥梁一词,我觉得更容易理解,哈哈,别“拍砖”呀!);

 

  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;

  上面语句中的DMA_InitStructure是一个DMA结构体,在库中有声明了,当然使用时就要先定义了;DMA_PeripheralBaseAddr是该结构体中一个数据成员,给DMA一个起始地址,好比是一个buffer起始地址,数据流程是:外设寄存器à DMA_PeripheralBaseAddàmemory中变量空间(或flash中数据空间等),ADC1_DR_Address是我定义的一个地址变量;

 

  DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC_ConvertedValue;

  上面这句很显然是DMA要连接在Memory中变量的地址,ADC_ConvertedValue是我自己在memory中定义的一个变量;

 

  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

  上面的这句是设置DMA的传输方向,就如前面我所说的,DMA可以双向传输,也可以单向传输,这里设置的是单向传输,如果需要双向传输:把DMA_DIR_PeripheralSRC改成DMA_DIR_PeripheralDST即可。

 

 

 DMA_InitStructure.DMA_BufferSize = 2;

  上面的这句是设置DMA在传输时缓冲区的长度,前面有定义过了buffer的起始地址:ADC1_DR_Address ,为了安全性和可靠性,一般需要给buffer定义一个储存片区,这个参数的单位有三种类型:Byte、HalfWord、word,我设置的2个half-word(见下面的设置);32位的MCU中1个half-word占16 bits。

 

 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

  上面的这句是设置DMA的外设递增模式,如果DMA选用的通道(CHx)有多个外设连接,需要使用外设递增模式:DMA_PeripheralInc_Enable;我的例子里DMA只与ADC1建立了联系,所以选用DMA_PeripheralInc_Disable

 

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

上面的这句是设置DMA的内存递增模式,DMA访问多个内存参数时,需要使用DMA_MemoryInc_Enable,当DMA只访问一个内存参数时,可设置成:DMA_MemoryInc_Disable。

 

 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

上面的这句是设置DMA在访问时每次操作的数据长度。有三种数据长度类型,前面已经讲过了,这里不在叙述。

 

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

与上面雷同。在此不再说明。

 

  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

  上面的这句是设置DMA的传输模式:连续不断的循环模式,若只想访问一次后就不要访问了(或按指令操作来反问,也就是想要它访问的时候就访问,不要它访问的时候就停止),可以设置成通用模式:DMA_Mode_Normal

 

  DMA_InitStructure.DMA_Priority = DMA_Priority_High;

  上面的这句是设置DMA的优先级别:可以分为4级:VeryHigh,High,Medium,Low.

 

  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

  上面的这句是设置DMA的2个memory中的变量互相访问的

 

  DMA_Init(DMA_Channel1,&DMA_InitStructure);

  前面那些都是对DMA结构体成员的设置,在次再统一对DMA整个模块做一次初始化,使得DMA各成员与上面的参数一致。

 

  /*DMA Enable*/

  DMA_Cmd(DMA_Channel1,ENABLE);

  哈哈哈!这一句我想我就不罗嗦了,大家一看就明白。

 

至此,整个DMA总算设置好了,但是,DMA通道又是怎样与外设联系在一起的呢?哈哈,这也是我当初最想知道的一个事情,别急!容我想喝口茶~~~~~~哈哈哈!

要使DMA与外设建立有效连接,这不是DMA自身的事情,是各个外设的事情,每个外设都有 一个xxx_DMACmd(XXXx,Enable )函数,如果使DMA与ADC建立有效联系,就使用ADC_DMACmd(ADC1,Enable); (这里我启用了ADC中的ADC1模块)。



主要特性


路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)