全球最实用的IT互联网信息网站!

AI人工智能P2P分享&下载搜索网页发布信息网站地图

当前位置:诺佳网 > 电子/半导体 > 存储技术 >

DMA是什么意思啊 DMA的使用思路

时间:2023-08-10 14:45

人气:

作者:admin

标签: dma    使用    意思  是什么 

导读:DMA是什么意思啊 DMA的使用思路-DMA(Direct Memory Access, 直接存储区访问) 为实现数据高速在外设寄存器与存储器之间或者存 储器与存储器之间传输提供了高效的方法。...

DMA(Direct Memory Access, 直接存储区访问) 为实现数据高速在外设寄存器与存储器之间或者存 储器与存储器之间传输提供了高效的方法。

之所以称之为高效,是因为 DMA 传输实现高速数据 移动过程无需任何 CPU 操作控制。

硬件层次上来说,DMA 控制器是独立于 Cortex-M4 内核的, 有点类似 GPIO、USART 外设一般,只是 DMA 的功能是可以快速移动内存数据。

DMA的通俗介绍

DMA(Direct Memory Access)直接存储通道,这是现在的MCU里基本都会标配的外设,但是很多工程师其实对它还是有些许陌生,因为这个东西就算不使用,也不影响外设的开发和使用。可是一旦对DMA的使用很熟练,那丝毫不亚于C语言熟练使用指针,能极大的提升外设的使用效率。

那这是一个什么玩意呢?简单的举个例子,应用层代码相当于商家,CPU相当于中间商,外设相当于批发商,在没有DMA时,如果应用代码想要获取外设信息ADC采样/UART数据/SPI接收数据等),那么需要通知一下中间商CPU想进点货,然后CPU再去找外设批发商要求发货。

批发商发货给中间商PCU,然后再由CPU给到应用层。不难看出这样的交互过程,中间商CPU忙的够呛,要和商家和批发商两头沟通,还要管下单(外设数据请求)和物流(外设数据传输)

图片

随着技术进步,现在的MCU都有比较快的运行速度,所以在没有极致速度要求时,CPU也忙的过来,大家也相安无事。

可是试想一下,一旦碰上双十一和春节抢车票这种的场景,这样低效率的方式则会严重耽误事,所以DMA则是一个提供了绕过中间商,商家直达批发商,达到厂家直销的效果。省去了中间大量的沟通成本,实现双赢。

图片

DMA的使用思路

DMA的使用也没有那么邪乎,很符合大家常规的一个思考。基本可以浓缩为当发生一个啥事的时候,需要某个人A给另一个人B捎个口信,让B知道是啥信息。套用个场景就是狗蛋来到旺财家门口让旺财妈知会一下,想和旺财一起出门玩(事件发生:狗蛋来找旺财玩),旺财妈妈朝屋里大喊一声:“旺财狗蛋喊你出门玩嘞!”(信息直接传递),然后旺财就知道了狗蛋来找他玩这件事。DMA的数据传输长度类似就是旺财妈那句话的断句,她可以一口气直接喊:“旺财狗蛋喊你出门玩嘞“,也可以喊:“旺财!狗蛋~ 喊你!出门~玩嘞!“这样两个字两个字的喊,虽然话是两个字的往外蹦,但是整体意思也是完整传达到了。那么这个说法可以套用到一个UART接收DMA传输,设置好事件条件是UART收到数据,那么就把UART外设数据寄存器(收到的数据)按照一个byte的长度直接发送到事先指定的RAM内存位置。

实际代码分析

综上可以看出DMA的使用配置最重要的内容就是触发条件,然后谁把信息告诉谁,每次传递多少数据。如下的范例代码,是配置了ADC每次完成采样后,能够将采样到的数据依次偏移放置在制定的数组种。

下面的代码主要关注的是结构体 DMA_InitStructure的配置。如下代码,可以看到触发条件是完成ADC采样后,ADC数据寄存器中的值就会直接通过DMA更新至指定的数组中,并且会自动完成数组中的指针偏移。在实际的使用中就能达到一次配置后,存放ADC数据的数组就会自动一直在刷新对应通道的ADC数值了。

void BspAdcDmaInit(ADC_Module* pADCx)  
{  
  DMA_InitType DMA_InitStructure;  
  DMA_ChannelType* DMAyChx;  
  u8 u8Offset = 0;  
  u8 u8Num = 0;  

  if(pADCx == ADC1)  
  {  
    u8Offset = 0;  
    DMAyChx = DMA1_CH1;  
    u8Num = ADC1CH_NUM;  
  }  
  else if(pADCx == ADC2)  
  {  
    u8Offset = ADC1CH_NUM;  
    DMAyChx = DMA1_CH8;  
    u8Num = ADC2CH_NUM;  
  }  
  else if(pADCx == ADC3)  
  {  
    u8Offset = ADC1CH_NUM + ADC2CH_NUM;  
    DMAyChx = DMA2_CH5;  
    u8Num = ADC3CH_NUM;  
  }  
  else if(pADCx == ADC4)  
  {  
    u8Offset = ADC1CH_NUM + ADC2CH_NUM + ADC3CH_NUM;  
    DMAyChx = DMA2_CH8;  
    u8Num = ADC4CH_NUM;  
  }  

  RCC_EnableAHBPeriphClk( RCC_AHB_PERIPH_DMA1|RCC_AHB_PERIPH_DMA2, ENABLE);  

  DMA_DeInit(DMAyChx);  
DMA_InitStructure.PeriphAddr   = (uint32_t)&pADCx- >DAT; //ADC数据寄存器  
DMA_InitStructure.MemAddr   = (uint32_t)&gu16AdcData[u8Offset]; //制定存放的数据地址  
DMA_InitStructure.Direction   = DMA_DIR_PERIPH_SRC;//传输方向为外设指向内存  
DMA_InitStructure.BufSize   = u8Num; //该ADC的一次全采样通道需要DMA传输次数  
DMA_InitStructure.PeriphInc   = DMA_PERIPH_INC_DISABLE;//DMA传输完无需变更外设数据寄存器地址  
DMA_InitStructure.DMA_MemoryInc   = DMA_MEM_INC_ENABLE;//指向内存的指针每完成一次DMA传输需要自动偏移  
DMA_InitStructure.PeriphDataSize   = DMA_PERIPH_DATA_SIZE_HALFWORD; //每次从外设获取的数据长度  
DMA_InitStructure.MemDataSize   = DMA_MemoryDataSize_HalfWord; //每次从内存获取的数据长度  
DMA_InitStructure.CircularMode   = DMA_MODE_CIRCULAR;//DMA会自行循环触发,直到完成BufSize完成后会自行恢复Mem最初指针并重新DMA传输  
DMA_InitStructure.Priority   = DMA_PRIORITY_HIGH;  
DMA_InitStructure.Mem2Mem   = DMA_M2M_DISABLE;  
DMA_Init(DMAyChx, &DMA_InitStructure);  
    
DMA_EnableChannel(DMAyChx, ENABLE);  

  ADC_EnableDMA(pADCx, ENABLE); //使能ADC完成采样触发DMA数据传输  
}
温馨提示:以上内容整理于网络,仅供参考,如果对您有帮助,留下您的阅读感言吧!
相关阅读
本类排行
相关标签
本类推荐

CPU | 内存 | 硬盘 | 显卡 | 显示器 | 主板 | 电源 | 键鼠 | 网站地图

Copyright © 2025-2035 诺佳网 版权所有 备案号:赣ICP备2025066733号
本站资料均来源互联网收集整理,作品版权归作者所有,如果侵犯了您的版权,请跟我们联系。

关注微信