7. DMA模块初见(ADC模块深入实践)

1.理解DMA概念

    学习DMA,首先我们要知道DMA是干什么的?DMA模块的主要作用是将内存或外设之间的数据进行移动,在stm32中ADC,串口,网口等都有自带DMA功能,我们知道通讯数据的传输一般都是数据量大,速度快,如果每次存储移动都通过cpu,一定程度上会影响工作效率,而ARM设计架构的时候显然考虑了这个问题,那就是DMA模块,它可以将数据从一块传递到另一块,且不需要CPU来干预,同时通过存储指针的自偏移,实现大量数据的顺序存储。

2.DMA库函数

   本实验中使用的开发板是stm32f107,它支持两个DMA外设,而本次只需要一个外设的一个通道,就选择DMA1_Channel1了。

DMA的相关寄存器很简单,就4个。具体寄存器地址参数可以看我总结的寄存器地址表。DMA的库函数并不多,那么我就按照可能用到的顺序依次解释学习。

typedef struct

{

u32 DMA_PeripheralBaseAddr;     //定义的外设基地址

u32 DMA_MemoryBaseAddr;          //定义的内存基地址

u32 DMA_DIR;                       //外设作为数据传输的来源还是目的地

u32 DMA_BufferSize;               //DMA通道的 DMA缓存的大小,单位为数据单位

u32 DMA_PeripheralInc;            //外设地址寄存器递增或不变

u32 DMA_MemoryInc;                //内存地址寄存器递增或不变

u32 DMA_PeripheralDataSize;     //外设数据宽度

u32 DMA_MemoryDataSize;          //内存数据宽度

u32 DMA_Mode;                      //DMA缓存工作方式

u32 DMA_Priority;                 //DMA工作优先级

u32 DMA_M2M;                        //DMA工作是内存到内存,还是外设到内存

}DMA_InitTypeDef; 

从上面可以知晓如何初始化配置DMA模块。

从要求可以看出,

uint16_t ADCConvertedValue;

DMA_InitTypeDef  DMA_InitStructrue;

复位DMA配置: DMA_DeInit(DMA1_Channel1);

按照上面的结构体依此配置DMA_InitStructrue的各项参数,初始化如下:

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);   //使能DMA1时钟

    DMA_DeInit(DMA1_Channel1);                              //选择与ADC1对应的DMA通道

    DMA_InitStructure.DMA_PeripheralBaseAddr =ADC1_DR_Address;  //ADC1数据寄存器基地址         

  DMA_InitStructure.DMA_MemoryBaseAddr=(uint32_t)&ADCConvertedValue;//内存数据地址                                 

  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;      //外设作为数据的来源地

  DMA_InitStructure.DMA_BufferSize = 1;                      //缓存区的字长

  DMA_InitStructure.DMA_PeripheralInc =DMA_PeripheralInc_Disable; //外设地址不自增

  DMA_InitStructure.DMA_MemoryInc =DMA_MemoryInc_Disable;   //内存地址不自增

  DMA_InitStructure.DMA_PeripheralDataSize =DMA_PeripheralDataSize_HalfWord;//外设数据长度半字16bit

  DMA_InitStructure.DMA_MemoryDataSize =DMA_MemoryDataSize_HalfWord;   //内存数据长度半字16bit

  DMA_InitStructure.DMA_Mode =DMA_Mode_Circular;    //循环模式,持续传送

  DMA_InitStructure.DMA_Priority =DMA_Priority_High;   //DMA优先级高

  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;    //外设到内存传递

  DMA_Init(DMA1_Channel1, DMA_InitStructrue);   //完成初始化配置。

初始化后,调用DMA_Cmd(DMA1_Channel2,  ENABLE); 即可使能选择的通道,如此就可以完成了DMA的从外设传递到内存中的初始化过程。

这样ADC1的规则组每转换完成一次,就会产生DMA请求,将转换完成的模拟量输入到ADCConvertedValue中,直接将这个数据通过串口1输出就可得到ADC1转换得结果。通过本次学习,我也了解了很多关于DMA的其它的东西,对DMA模块有了更深刻的了解。

   以下来自百度百科,以及自己的总结

  1.DMA 传输将数据从一个地址空间复制到另外一个地址空间,这部分是由DMA控制器实现的,不需要依靠CPU的大量的数据采集传送,节省cpu资源。从上面我们也可以看到,DMA在ADC转换,串口输入输出方面有很大优势。

  2.DMA工作包含四个过程

    DMA请求-〉DMA响应-〉DMA传输-〉DMA结束

  3.DMA传送方式有以下三种

(1)停止CPU访内存;

    当外围器件有一批数据需要传送时,DMA给CPU发送停止信号,CPU停止访问内存,释放相关总线控制权,DMA获得总线控制权后开始传递数据,完成后将总线控制权交给CPU。一次DMA传送结束。

   优点:控制简单,用于速率很高的组传送

   缺点:内存的效能没有发挥,一部分时间内存处于空闲状态。这是因为DMA传送阶段有很多时间是在读取外设的数据,总线一段时间肯定是空闲的,而这部分时间足够CPU进行内存的访问。

(2)周期挪用(ADC转换采用的正是这种方式)

当I/O设备没有DMA请求时,CPU按程序要求访问内存;一旦I/O设备有DMA请求,则由I/O设备挪用一个或几个内存周期。

(3)DMA与CPU交替访内存.

此外,DMA在嵌入式开发中还有以下知识点:

1.Cortex-M3的芯片中不同外设对应的是不同的DMA通道的,不能随便选择。

2. DMA_BufferSize代表着缓冲字节的大小,

  DMA_BufferSize表示的是为传送的字节数目,也就是循环缓存模式下外设地址或者内存地址递增的数目。

与地址是否递增类项搭配使用即可实现一组数的传递,在USART和ADC中都有用处。 

3. DMA_Mode 缓存工作方式

DMA_Mode_Circular循环模式:地址递增结束后回到初始地址,进行下一轮的循环传送

DMA_Mode_Normal普通模式:仅传送一次,传递完成后结束。


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这段代码是用于配置和启用DMA1通道1的功能,实现ADC采集数据的自动传输。 具体的意思如下: 1. DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; 配置DMA传输的外设地址为ADC1的数据寄存器地址。 2. DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValue; 配置DMA传输的存储器地址为ADC_ConvertedValue变量的地址,即将采集到的数据存储到ADC_ConvertedValue数组中。 3. DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; 配置DMA传输方向为从外设到存储器。 4. DMA_InitStructure.DMA_BufferSize = 2; 配置DMA传输数据的数量为2,即每次传输两个半字(16位)的数据。 5. DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 配置DMA传输过程中外设地址不自增。 6. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 配置DMA传输过程中存储器地址自增。 7. DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord; 配置DMA传输数据宽度为半字(16位)。 8. DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; 配置DMA传输数据宽度为半字(16位)。 9. DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; 配置DMA传输模式为循环传输。 10. DMA_InitStructure.DMA_Priority = DMA_Priority_High; 配置DMA传输的优先级为高。 11. DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; 配置DMA传输模式为非存储器到存储器传输。 12. DMA_Init(DMA1_Channel1, &DMA_InitStructure); 将以上配置应用到DMA1通道1上。 13. DMA_Cmd(DMA1_Channel1, ENABLE); 启用DMA1通道1。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值