【STM32】DMA

用于减轻CPU压力的神器,相当于直接将外设映射到内存数据上。

大部分图片来源:正点原子HAL库课程

 专栏目录:记录自己的嵌入式学习之路-CSDN博客


目录

0    概述

1    原理(用于个人理解的,非常重要!)

1.1    DMA请求

1.2    循环模式与DMA请求的关系

1.3    传输完成中断(TC)发生的时机

2    硬件情况

3    作用

4    DMA的优先级

4.1    软件优先级

4.2    硬件优先级

4.3    优先级的作用

5    数据流方向

5.1    外设到存储器

5.2    存储器到外设

5.3    存储器到存储器

5.4    配置

6    外设/存储器地址增量模式

7    传输的数据宽度

8    传输结束时机(循环与否)

8.1    中断的不同

8.2    对循环模式的支持

9    其他特性

9.1    最大传输数

9.2    内存到内存的传输

10    相关HAL库函数

11    重要结构体

12    配置步骤

13    注意事项


0    概述

DMA,全称为:Direct Memory Access,即直接存储器访问。

DMA牛逼的地方应该就是将一个外设的数据内容直接映射到内存中的一堆数据中,通过读数据就读到了外设通过GPIO输入的某些值,就不需要使用CPU费劲巴拉地去访问寄存器获取这些值。


1    原理(用于个人理解的,非常重要!)

1.1    DMA请求

如果外设想要通过DMA来传输数据,必须先给DMA控制器发送DMA请求,DMA收到请求信号之后,控制器会给外设一个应答信号,当外设应答后且DMA控制器收到应答信号之后,就会启动DMA的传输,直到传输完毕。

1.2    循环模式与DMA请求的关系

我的理解是:

在非循环模式下,外设发出了DMA请求,若此时CNDTR寄存器的值不为0,则DMA根据设定的数据宽度执行一次数据搬运;而如果CNDTR寄存器的值已经为0了,DMA将不会响应外设的数据搬运请求。

而在循环模式下,CNDTR寄存器清零后会重新置为用户设定的值,并继续响应外设的DMA请求。

1.3    传输完成中断(TC)发生的时机

CNDTR寄存器的值减到0的时候。并不是一个数据宽度搬运完毕的时候。


2    硬件情况

STM32F1有两个DMA控制器:DMA1和DMA2。其分别拥有7个和5个通道。各通道对应不同的外设,见下图:


  • 可在《STM32F10xxx参考手册》查询。

3    作用

DMA传输将数据从一个地址空间复制到另一个地址空间。

其无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场过程,通过硬件为RAM和IO设备开辟一条直接传输数据的通道,使得CPU的效率大大提高。减轻了CPU的负担。


4    DMA的优先级

4.1    软件优先级

程序可设置DMA通道的软件优先级,有最高、高、中、低四个优先级。

4.2    硬件优先级

在软件优先级相同的情况下,硬件的通道编号越小,优先级越高。且DMA1优先级比DMA2高。

4.3    优先级的作用

多个请求通过逻辑或输入到DMA控制器,只能有一个请求有效。所以需要优先级处理这个情况。


5    数据流方向

5.1    外设到存储器

当我们使用从外设到存储器传输时,以ADC采集为例。DMA外设寄存器的地址对应的就是ADC数据寄存器的地址,DMA存储器的地址就是我们自定义的变量(用来接收存储AD采集的数据)的地址。方向我们设置外设为源地址。

5.2    存储器到外设

当我们使用从存储器到外设传输时,以串口向电脑端发送数据为例。DMA外设寄存器的地址对应的就是串口数据寄存器的地址,DMA存储器的地址就是我们自定义的变量(相当于一个缓冲区,用来存储通过串口发送到电脑的数据)的地址。方向我们设置外设为目标地址。

5.3    存储器到存储器

当我们使用从存储器到存储器传输时,以内部FLASH向内部SRAM复制数据为例。DMA外设寄存器的地址对应的就是内部FLASH(我们这里把内部FALSH当作一个外设来看)的地址,DMA存储器的地址就是我们自定义的变量(相当于一个缓冲区,用来存储来自内部FLASH的数据)的地址。方向我们设置外设(即内部FLASH)为源地址。跟上面两个不一样的是,这里需要把DMA_CCR位14:MEM2MEM:存储器到存储器模式配置为1,启动M2M模式。

5.4    配置

寄存器中通过MEM2MEM、DIR两个寄存器对数据的流向进行配置:



6    外设/存储器地址增量模式

就是传输过程中有一个指针指向外设/存储器,在写完一个后自动往后移动指针。对于串口传输的情况,由于存储器是需要传输完一个自动往下再传输,因此应该使能存储器地址增量模式。而对于外设串口,因为只是往其DR寄存器中传输数据,并没有指针移动的操作,因此就不需要使能外设地址增量模式。

野火HAL库教程的解释:以串口向电脑发送数据为例,要发送的数据很多,每发送完一个,那么存储器的地址指针就应该加1,而串口数据寄存器只有一个,那么外设的地址指针就固定不变。


7    传输的数据宽度

在寄存器可以设置存储器和外设的数据宽度,一般来说,两者应该设置为一致的,一般以外设的为准。例如串口的数据寄存器是8位的,因此外设和存储器的数据宽度都要设置为8位。

当实在是需要源数据和目标数据宽度不一致的情况时,需要查阅《STM32F10xxx参考手册》,如下图的表格。


8    传输结束时机(循环与否)

数据什么时候传输完成,我们可以通过查询标志位或者通过中断的方式来鉴别。每个DMA通道在DMA传输过半、传输完成和传输错误时都会有相应的标志位,如果使能了该类型的中断后,则会产生中断。有关各个标志位的详细描述请参考DMA中断状态寄存器DMA_ISR的详细描述。

传输完成还分两种模式,是一次传输还是循环传输,一次传输很好理解,即是传输一次之后就停止,要想再传输的话,必须关断DMA使能后再重新配置后才能继续传输。循环传输则是一次传输完成之后又恢复第一次传输时的配置循环传输,不断的重复。具体的由DMA_CCR寄存器的CIRC循环模式位控制。

8.1    中断的不同

在循环模式下,每次DMA传输完成都会触发对应通道的中断服务函数;

⚠️但在非循环模式下,DMA的公共中断服务函数会调用__HAL_DMA_DISABLE_IT将中断失能,因此如果需要其始终起作用,就需要在中断服务函数中加上__HAL_DMA_ENABLE_IT。

8.2    对循环模式的支持

⚠️存储器到存储器的数据流向是不支持循环模式的。


9    其他特性

9.1    最大传输数

65535个字节。

在寄存器中,有一个寄存器存放当前剩余传输数目。

在非循环模式下,用户使能DMA并对该寄存器进行赋值N后,DMA会发送N个字节的数据,等N被倒数到0后,数据发送完毕。要再次发送就需要重新使能DMA并赋值N。

若在循环模式下N在减到0后自己就会循环回去N,从而循环发送。

9.2    内存到内存的传输

F1系列所有的DMA及DMA通道都支持内存到内存的传输。


10    相关HAL库函数


11    重要结构体


12    配置步骤

  • 非循环模式下,发送数据的准备步骤
    • __HAL_DMA_DISABLE(…);
    • 设置数量寄存器,如:dma_handle.Instance->CNDTR = len;
    • __HAL_DMA_ENABLE(…);
  • 查询通道状态的标志位
    • __HAL_DMA_GET_FLAG(&g_dma_handler, DMA_FLAG_TC1)
    • 这里的TC指的就是Transmit Complete,发送完成。
  • 清除通道状态的标志位
    • __HAL_DMA_CLEAR_FLAG(&g_dma_handler, DMA_FLAG_TC1)
  • 失能DMA
    • HAL_UART_DMAStop()
  • ⚠️⚠️⚠️__HAL_LINKDMA(__HANDLE__, __PPP_DMA_FIELD__, __DMA_HANDLE__)
    • 该宏函数用于将外设和DMA连接起来,让DMA知道处理哪个外设的数据,其中:
    • __HANDLE__为外设的句柄,__PPP_DMA_FIELD__为外设句柄中DMA句柄的名称(进入外设句柄的定义里能看到,如下图例子),__DMA_HANDLE__为DMA的句柄。
    • 需要注意的是:__HAL_LINKDMA宏函数的最后一个参数(即DMA句柄)无需加地址符,因为其内部就有了,因此调用的形式为:
      __HAL_LINKDMA(&adc_handle, DMA_Handle, dma_handle);
  • ⚠️⚠️⚠️HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
     
    • HAL_DMA_Start_IT函数的SrcAddress和DstAddress分别表示DMA数据的来源和目标地址,一般就是外设的DR寄存器或者是变量或数组。若是要传入数组的话会相对比较麻烦,见下图array是个数组:

       
      也可以这样转:
      (uint32_t)&array
    • 调用该函数时最好SrcAddress和DstAddress都强转成uint32_t再传入,像上图那样,否则会有警告。

13    注意事项

  • HAL_DMA_Init函数没有对应的MSP初始化函数,因此其时钟的开启代码要自己放好执行。
  • 如果有外设需要使用DMA,就要确认其使用的是DMA1还是DMA2,还要确认其使用的通道,具体就是查15.2里面的那个表就可以了。
  • 在设置DMA的参数(如传输数目CNDTR)时,需要确保DMA不在传输状态,常用while配合CCR的位0判断,或使用while配合DMA的传输完成TC标志做判断:

  • 34
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: STM32中的DMA(直接内存访问)是一种高效的数据传输机制,它可以以较少的CPU干预完成大量的数据传输。 DMA FIFO是DMA传输中的一个缓冲区,它可以储存数据以便DMA直接从中读取和写入数据。DMA FIFO可以大大提升DMA传输的效率,因为它可以避免DMA频繁访问内存,从而减少CPU的干预,提升数据传输的速率。 在STM32中,不同的DMA通道都有自己独立的DMA FIFO。DMA FIFO可以通过编程控制其大小和数据传输的方向。此外,DMA FIFO还支持半总线传输和内存突发传输等高级功能,以进一步提高数据传输的效率。 需要注意的是,DMA FIFO的大小不能太小,否则会影响传输速度。同时,在使用DMA FIFO时,需要注意内存的地址对齐,否则会影响DMA传输的效率。 总之,STM32 DMA FIFO是一种高效的DMA缓冲区,它能够大大提高数据传输的效率,减少CPU的干预,是STM32高效数据传输的重要手段之一。 ### 回答2: STM32 DMA FIFO是一种在STM32微控制器内部使用的先进的数据传输机制,旨在提高数据传输的效率和可靠性。DMA(FIFO)是指直接内存存储器访问(FIFO)的简称,这种传输方式可以通过DMA控制器自动处理,而无需CPU的干预。 STM32 DMA FIFO可以通过提供缓存缓冲区来处理和管理数据传输,这些缓存区是可以在存储器或外设之间共享数据的独立存储器区域。缓存区的大小和数量可以根据应用程序的数据传输速率和带宽要求进行配置。通过使用FIFO机制,可以缓解传输速率不匹配的问题,并且可以在数据传输时提供额外的保密性。 STM32 DMA FIFO的优点包括高效的数据传输速率,使得数据传输更加快速和可靠;同时,它还可以减少CPU的负担,提高程序执行效率。STM32 DMA FIFO对于大数据传输、高速传输以及多模块数据传输等应用非常有用。 因此,STM32 DMA FIFO已经成为了STM32微控制器的一个标准组件,许多工业自动化、智能制造和物联网应用程序中,都广泛采用了这种数据传输机制。 ### 回答3: STM32 DMA FIFO是STM32微控制器中的一种DMA传输方式,它使用了FIFO缓冲区来提高DMA传输效率。FIFO(First-In-First-Out)的缓冲区可以在一端输入数据,在另一端输出数据,所有数据按照入队的顺序依次出队。在DMA传输中,FIFO缓冲区可以减少DMA传输对CPU的干扰,并且可以缓存大量的数据,以增强数据传输的连续性与稳定性。通过使用DMA FIFO,可以在DMA传输期间减少数据丢失和重复读取以及提高数据传输的吞吐量。 STM32 DMA FIFO的主要特点包括: 1. 多通道支持:STM32 DMA FIFO可以支持多个通道同时进行DMA传输,并且可以进行通道间的数据拷贝。 2. 高效传输:使用DMA FIFO可以减少CPU的干扰,并且可以增强数据传输的连续性,从而提高数据传输的效率。 3. 灵活配置:STM32 DMA FIFO可以通过编程的方式配置传输方式、传输数据长度、传输地址等参数,以适应不同的应用场景。 总之,STM32 DMA FIFO是一种高效的DMA传输方式,适用于需要高效、稳定、连续的数据传输场景,例如音频、视频、存储器等大量数据传输场景。它可以提高数据传输效率,减少CPU的负担,提高系统的稳定性和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值