什么是DMA?
DMA,全称为Direct Memory Access, 直接存储器访问. 用于在外设与存储器之间以及存储器与存储器之间提供高速数据传
输。可以在无需任何 CPU 操作的情况下通过 DMA 快速移动数据。这样节省的 CPU 资源可供其他操作使用。
我们知道CPU有很多功能,单片机的核心就是CPU.
CPU无时无刻不在处理着大量的事务,但有些事情却没有那么重要,比方说数据的复制和存储数据,如果我们把这部分的CPU资源拿出来,让CPU去处理其他的复杂计算事务,是不是能够更好的利用CPU的资源呢?
DMA就是基于以上设想设计的,它的作用就是解决大量数据转移过度消耗CPU资源的问题。有了DMA使CPU更专注于更加实用的操作----计算、控制等。
DMA传输参数(结构体成员):
比如我们定义一个u32类型数组,直接写数组首地址(直接使用数组名)即可,在DMA传输的时候就可以发送数组数据,或者把数组用来接收其他数据。
比如我们要从内存(存储器)中传输64个字节到串口,如果设置为循环传输,那么它会在64个字节传输完成之后继续从内存的第一个地址传输,如此循环。
常见问题:
如果源端地址宽度<目标地址宽度,如源端地址宽度=8,目标地址宽度=16,那么源端地址每次偏移为0x1,目标地址每次偏移为0x2。数据没有丢失,但会出现8位数据占16位数据的情况,而此时,配置的左对齐和右对齐就有了作用。
比方说源数据为0xB1,当目标地址宽度为16的时候,传输后结果为0x00B1
如果源端地址宽度>目标地址宽度,如源端地址宽度=16,目标地址宽度=8,那么源端地址每次偏移为0x2,目标地址每次偏移为0x1。且数据会丢失!
比方说源数据为0xB1B2,当目标地址宽度为8的时候,传输后结果为0xB2,只取低位.
如果源端地址宽度=目标地址宽度,如源端地址宽度=目标地址宽度=16,那么源端地址每次偏移为0x2,目标地址每次偏移为0x2。数据没有丢失,即源数据是什么,目标数据就是什么。
仲裁器的作用是确定各个DMA传输的优先级
仲裁器根据通道请求的优先级来启动外设/存储器的访问。
优先权管理分2个阶段:
比如:如果软件优先级相同,通道2优先于通道4。
注意: 在大容量产品和互联型产品中,DMA1控制器拥有高于DMA2控制器的优先级。
当通道配置设定为循环模式时,在最后一次传输后DMA 通道 x 数据传输量寄存器的内容会恢复成初始值。DMA会继续进行传输
在FIFO模式下,每次产生外设请求时候,数据流都会启动数据源到FIFO的传输
当FIFO达到阈值时候,FIFO的内容移除并且存储到目标中
不再使用FIFO的阈值级别控制: 每完成一次从外设到FIFO的数据传输后,相应额数据立即就会移出并且存储到目标中
使能这种模式时,数据流会立即启动传输,从源完全填充 FIFO。每次发生外设请求,FIFO 的内容都会移出并存储到目标中。当 FIFO 的级别小于或等于预定义的阈值级别时,将使用存储器中的数据完全重载 FIFO。
不使用 FIFO 的阈值级别。一旦使能了数据流,DMA 便会预装载第一个数据,将其传输到内部 FIFO。一旦外设请求数据传输,DMA 便会将预装载的值传输到配置的目标。然后,它会使用要传输的下一个数据再次重载内部空 FIFO。
DMA 通道在没有外设请求触发的情况下同样可以工作。通过将 DMA_SxCR 寄存器中的使能位 (EN) 置 1 来使能数据流时,数据流会立即开始填充 FIFO,直至达到阈值级别。达到阈值级别后,FIFO 的内容便会移出,并存储到目标中。如果 DMA_SxNDTR 寄存器达到零或 DMA_SxCR 寄存器中的 EN 位由软件清零,传输即会停止。
使用存储器到存储器模式时,不允许循环模式和直接模式。