今天刚看了一个ADC采集的程序,和之前用其他单片机写的程序还是有比较大的差别,这个差别主要就在DMA。这里面总结一下,有一部分是转载别人的。

 

什么是STM32的DMA?其全称是:Direct Memory Access;根据ST公司提供的相关信息,DMA是STM32中一个独立与Cortex-M3内核的模块,有点类似与ADC、PWM、TIMER等模块;主要功能是通信“桥梁”的作用,可以将所有外设映射的寄存器“连接”起来,这样就可以高速问各寄存器,其传输不受CPU的支配,传输还是双向的;例如,从“表面”上看,它可以将flash中的数据与储存器中变量建立通讯,还可以将一外设的积存器或缓冲器与另外设的寄存器或缓冲器建立双向通讯,有点像把外设硬件之间用“导线”连接在一起了。其间的通讯不占CPU资源,访问速度高,对于实时性强的应用将是一个很好的选择;当然,对于实时性非常强的,建议还是采用专用的DSP芯片


怎样启用DMA?首先,众所周知的是初始化,任何设备启用前都要对其进行初始化,要对模块初始化,还要先了解该模块相应的结构及其函数,以便正确的设置;由于DMA较为复杂,我就只谈谈DMA的基本结构和和常用函数,这些都是ST公司提供在库函数中的。


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

 

DMA_DeInit(DMA_Channel1);


上面这句是给DMA配置通道,根据ST提供的资料,STM3210Fx中DMA包含7个通道(CH1~CH7),这里需要选择一个传输通道

 

DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;


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

 

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的一个简单应用,后面做很多设计在数据传输上需要做这种转变,特别是像我这样从单片机学过来的,现在里面有了更好的方式要学会去运用,不能固守原来单片机的设计思路。这个相信也是后面学习中很重要的一部分。

关键字:STM32  DMA  使用入门 引用地址:STM32中DMA的使用入门

上一篇:STM32启动过程解析-2.02固件库启动文件分析
下一篇:Keil STM32工程环境搭建

推荐阅读

自从华为发布了GPU Turbo技术后,经过不少KOL以及用户的亲自检测,麒麟970确实能和骁龙845一战。虽然目前外界还是不太明白原理,但GT技术的实力已经被认可了,吃瓜群众表现想看看高通的反应。近日高通终于对GT技术发起挑战,声称要推出安卓Turbo,游戏体验也会再进一步!  先说说编编对于这件事的想法;首先,高通确实感受到了来自华为麒麟的压力,此前...
高手对决,胜负只在毫厘之间。不论体育竞技、“蔡周”流量数据之争,还是技术领域的一次次突破,在各自都逼近极限的情况下。1%的提升往往能带来远超1%的效果。新能源汽车行业有一个共识,为了进一步提高效率,传统圆线绕组电机最终要被淘汰,而扁线电机绕组的Hair-pin电机将成为未来的发展方向。雪佛兰Volt与丰田第四代Pruis早已经开始应用Hair-pin电机,...
据悉,为了应对美国对华为的技术打压,规避应用美国技术制造终端产品,华为近日启动了“南泥湾项目”。 该项目重点加速推进华为笔记本电脑业务和智慧屏业务,这两大类产品不包含美国技术。今年 8 月中旬华为将发布新款笔记本电脑产品。 据了解,华为用“南泥湾”命名的这个项目,意思是“在困境期间,希望实现自给自足”。在这个过程中,笔电(笔记本电...
今天想分享一种超级实用的步进电机调速算法,这种算法在步进电机调速方案中可以说是一种非常优异的方案。 梯形调速算法为啥需要设计一个调速算法呢?步进电机不是给多少脉冲就动多少步吗?但是带上负载了就可能失步,所谓失步,简单理解就是实际电机轴转过的度数,没有输入脉冲对应度数多。为什么会这样呢?电机的扭矩有可能无法驱动负载。一般会做一个启...

史海拾趣

小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved