历史上的今天
返回首页

历史上的今天

今天是:2025年01月04日(星期六)

2019年01月04日 | STM32之DMA的认识和使用

2019-01-04 来源:eefocus

DMA是什么? 

DMA(Direct Memory Access,直接内存存取) 是所有现代电脑的重要特色,它允许不同速度的硬件装置来沟通,而不需要依赖于 CPU 的大量中断负载。否则,CPU 需要从来源把每一片段的资料复制到暂存器,然后把它们再次写回到新的地方。在这个时间中,CPU 对于其他的工作来说就无法使用。(百度百科) DMA可以看作是数据搬运工

DMA有什么用? 

直接存储器存取用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU的干预,通过DMA数据可以快速地移动。这就节省了CPU的资源来做其他操作。

stm32有多少资源? 

有两个DMA控制器,DMA1有7个通道,DMA2有5个通道。


数据从什么地方到什么地方? 

外设到SRAM(I2C/UART等获取数据并送入SRAM); 

SRAM的两个区域之间; 

外设到外设(ADC读取数据后送到TIM1控制其产生不同的PWM占空比); 

SRAM到外设(SRAM中预先保存的数据送入DAC产生各种波形); 等等等..


DMA的使用: 


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


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模块)。


一个简单的例子:


/* DMA1 channel6 configuration */

DMA_DeInit(DMA1_Channel6);

  //peripheral base address

DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SRC_Const_Buffer;

  //memory base address   

DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)DST_Buffer;

  //数据传输方向    Peripheral is source               

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

//缓冲区大小 Number of data to be transferred (0 up to 65535).数据传输数目     

DMA_InitStructure.DMA_BufferSize = BufferSize;

   // the Peripheral address register is incremented       

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;

  //the memory address register is incremented

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

//the Peripheral data width       

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; 

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;

DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;

DMA_InitStructure.DMA_Priority = DMA_Priority_High;

//the DMAy Channelx will be used in memory-to-memory transfer

//DMA通道的操作可以在没有外设请求的情况下进行,这种操作就是存储器到存储器模式。

DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;   

DMA_Init(DMA1_Channel6, &DMA_InitStructure);


/* Enable DMA1 Channel6 Transfer Complete interrupt */

DMA_ITConfig(DMA1_Channel6, DMA_IT_TC, ENABLE);



/* Enable DMA1 Channel6 transfer */

DMA_Cmd(DMA1_Channel6, ENABLE);


推荐阅读

史海拾趣

B&F Fastener Supply公司的发展小趣事

随着全球电子市场的不断扩大,B&F Fastener Supply公司开始将目光投向海外市场。公司积极开拓国际市场,与多个国家和地区的电子企业建立合作关系。同时,B&F还加大了对海外市场的投入力度,通过设立海外分支机构、参加国际展会等方式提升品牌知名度和市场份额。

这些故事虽然基于假设和推测,但试图展现了B&F Fastener Supply公司在电子行业中的可能发展历程。请注意,这些故事并非真实事件,仅用于说明公司在电子行业发展的可能性和方向。

ASSMANN WSW components公司的发展小趣事

随着公司规模的扩大和产品质量的提升,ASSMANN WSW components公司开始积极拓展全球市场。通过与全球知名企业的合作,公司成功打入国际市场,产品远销海外。同时,公司还积极参加国际电子展会和交流活动,与全球同行建立了广泛的合作关系。这些举措不仅提升了ASSMANN WSW的品牌知名度和影响力,还为公司带来了更多的商业机会和发展空间。

BESTECH公司的发展小趣事

ASSMANN WSW components公司一直致力于技术创新和产品研发。在某个关键时刻,公司研发团队成功开发出了一种具有革命性的新型连接器,这种连接器不仅性能稳定、寿命长,而且具有极高的可靠性和安全性。这一技术突破使得ASSMANN WSW在电子元件市场上脱颖而出,迅速成为行业内的佼佼者。

Cristek Interconnects Inc公司的发展小趣事

Cristek Interconnects Inc公司在技术创新和质量管理的双重驱动下,开始积极拓展市场。公司不仅在国内市场取得了显著的成绩,还积极开拓国际市场。通过与国外知名企业的合作,Cristek的产品成功打入国际市场,进一步提升了公司的知名度和影响力。

三环(CCTC)公司的发展小趣事

随着科技的不断进步和市场环境的变化,三环(CCTC)公司认识到科技创新是企业持续发展的关键。因此,公司加大了研发投入力度,引进和培养了一批高素质的研发人才,建立了以博士、硕士为主组成的技术研发团队。同时,公司积极承担并完成多个国家、省级重点科研项目,不断开展新材料、新产品、新技术的研究与创新。这些努力使公司在多个领域取得了突破性的成果,实现了转型升级。

FIDELIX公司的发展小趣事

FIDELIX公司成立于1990年,最初只是一家小型半导体研发公司。在韩国半导体产业蓬勃发展的背景下,FIDELIX凭借其对技术的执着追求和对市场的敏锐洞察,逐渐在NAND FLASH(闪存)和SDR/DDR(单/双数率同步动态存储器)等存储芯片领域取得突破。经过多年的努力,FIDELIX在韩国市场上确立了其存储芯片研发及销售的地位,成为仅次于三星、SK海力士的第三大MEMORY(存储器)生产厂商。

问答坊 | AI 解惑

jffs2文件系統挂載出錯,求助

瘋狂的出jffs2_scan_eraseblock錯誤。 我使用的是 8M Nor Flash 但是 沒有分區,請問 分區的作用是什麽? 這個問題最可能的原因是什麽,仰仗各位的經驗了。…

查看全部问答>

出现: hr -2147221164 {没有注册类别 } HRESULT

        if (dlgPush.DoModal())         {                 //得到pCERDA接口                 HRESULT hr = CoCr ...…

查看全部问答>

jedec_probe探测SST39vf3201的疑问

CPU:NXP LPC2478 Flash:NOR SST39VF3201:4MB,4k扇区,地址:0x81000000 想在4M的NOR flash上作jffs2根文件系统,自己写了MTD驱动: #define FLASH_BASE_ADDR                0x81000000 #define F ...…

查看全部问答>

求bin、com、exe二进制文件之间的区别

求bin、com、exe等二进制文件之间的区别…

查看全部问答>

我现在从事MIS系统的开发,想向硬件开发上深入一下,大家给点意建!!!

我已经从事MIS开发二年多了,主要是J2EE.这类开发是纯软件的,感觉现在做起来很辛苦而且市场越来越不理想了.     现在的软件产品能体现出大利润的我发现都要和硬件结合,于是我想在这方面深入一下,业内的朋友能不能给点议建?   &nbs ...…

查看全部问答>

南京招聘:有嵌入式及硬件基础知识的Delphi BCB程序员,从事监控主站开发

南京招聘:有嵌入式及硬件基础知识的Delphi BCB程序员,从事监控主站开发 要求:      1:熟悉Delphi开发环境。      2:熟练使用SQL-Server编程语言      3:了解一定的硬件知识和 ...…

查看全部问答>

求DXP常用元件封装库 pcblib格式的

求DXP常用元件封装库 pcblib格式的 邮箱是xubbwd@126.com…

查看全部问答>

请教:液晶显示屏选型

本帖最后由 dontium 于 2015-1-23 13:32 编辑 打算利用TMS320LF2407A作主控芯片,作一些有关控制和AD采样方面的课题,要求在液晶显示屏上能实时显示信号波形和幅值。不知用什么显示屏适合,望大虾指点!! 谢了先 …

查看全部问答>