欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 幼教 > DMA学习笔记

DMA学习笔记

2025/9/20 1:58:48 来源:https://blog.csdn.net/weixin_53070140/article/details/140160109  浏览:    关键词:DMA学习笔记

参考文章

https://blog.csdn.net/as480133937/article/details/104927922

DMA简介

DMA,全称Direct Memory Access,即直接存储器访问。DMAC 即 DMA 控制器,提供了一种硬件的数据传输方式,无需 CPU 的介入,可以处理外设和存储器之间或者存储器和存储器之间的传输数据。因无 CPU 介入,从而使 CPU 可以专注在处理其他系统功能上。由此可以减轻CPU的负担,使得更多的CPU资源分配到其他的任务处理上面去。

主要配置参数

了解DMA是什么,以及为什么要使用DMA后,我们之后就是要知道如何去配置DMA,以及需要配置哪些参数。下面是一些主要需要配置的参数。

DMA的传输通道

不同单片机有不同的通道可供使用,结合实际资源参数进行选择。

目标外设和源外设号(有些可能是直接配置地址)

DMA的传输方式

  • 外设到内存
  • 内存到外设
  • 内存到内存
  • 外设到外设

数据传输宽度

这个可以根据实际需求配置成一个字节、半个字、全字这三种方式

  • DMA_SRC_WIDTH_BYTE    
  • DMA_SRC_WIDTH_HALF_WORD
  • DMA_SRC_WIDTH_WORD   

模式设置

  • 模式可以设置为正常模式(开启之后仅只传输一次)
  • 循环模式(会一直循环传输数据)

地址生成方式

所谓地址生成方式,就是看你使不使用,地址递增或者固定地址。也就是

固定模式和递增模式。

  • 在固定模式中,地址一直固定为初始化的基地址(DMACCxSrcAddr、 DMACCxDestAddr)。
  • 在递增模式中,下一次传输数据的地址是当前地址加 1(或者 2, 4),这个值取决于数据
  • 传输宽度

具体配置代码

void DMA_SPITransmit_Init(void)
{DMA_SPIT_Handle.Instance              = DMA_Channel1;DMA_SPIT_Handle.Init.Data_Flow        = DMA_DATA_FLOW_M2P;DMA_SPIT_Handle.Init.Request_ID       = REQ3_SPI2_SEND;DMA_SPIT_Handle.Init.Mode             = DMA_NORMAL;DMA_SPIT_Handle.Init.Source_Inc       = DMA_SOURCE_ADDR_INCREASE_ENABLE;DMA_SPIT_Handle.Init.Desination_Inc   = DMA_DST_ADDR_INCREASE_DISABLE;DMA_SPIT_Handle.Init.Source_Width     = DMA_SRC_WIDTH_BYTE;DMA_SPIT_Handle.Init.Desination_Width = DMA_DST_WIDTH_BYTE;/*-----------------------------------------------------------------------------------*//* Note:If user dons not apply interrupt, Set DMA_ITC_Callback?¢DMA_IE_Callback NULL *//*-----------------------------------------------------------------------------------*/DMA_SPIT_Handle.DMA_ITC_Callback = NULL;DMA_SPIT_Handle.DMA_IE_Callback  = NULL;HAL_DMA_Init(&DMA_SPIT_Handle);__HAL_LINK_DMA(SPI_Handle, HDMA_Tx, DMA_SPIT_Handle);
}

我这里使用的是SPI+DMA配置方式,单片机还是航芯的单片机,选择了寄存器地址(目标地址)不变,源地址(数据地址)递增,这样配置满足我们需求。然后传输完成回调函数和传输出错回调函数暂时没有配置。

DMA中断

每个 DMA 通道都有一个专用的中断。中断事件有两种类型:传输完成传输错误。 每一个中断事件在状态寄存器和清除寄存器中有专用的标志位。通过检测两种中断标志位可以获取我们DMA的传输情况。

__weak void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
{uint32_t lu32_Channel_Index;/* Get DMA Channel number */lu32_Channel_Index = ((uint32_t)(hdma->Instance) - (uint32_t)(DMA_Channel0)) / 0x20;/* Channel has been interrupted */if (DMA->INT_STATUS & (1 << lu32_Channel_Index)){/* Transfer complete interrupt */if (DMA->INT_TC_STATUS & (1 << lu32_Channel_Index)){DMA->INT_TC_CLR |= (1 << lu32_Channel_Index);if (NULL != hdma->DMA_ITC_Callback){hdma->DMA_ITC_Callback();}}/* Transfer error interrupt */if (DMA->INT_ERR_STATUS & (1 << lu32_Channel_Index)){DMA->INT_ERR_CLR |= (1 << lu32_Channel_Index);if (NULL != hdma->DMA_IE_Callback){hdma->DMA_IE_Callback();}}}}

上面就是在触发中断后在中断函数中处理函数的中断程序,主要逻辑就是先获取哪个中断触发,然后判断触发源(传输完成或者传输错误)。

总结

DMA配置使用起来参数不多也比较简单,但是要真正使用并理解还是需要时间去消化。像之前不使用DMA不知道有啥作用,只模糊地知道可以帮CPU减负,导致很多情况下都乱用DMA。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词