本帖最后由 redone 于 2021-10-12 19:28 编辑
使用DMA,最核心就是配置要传输的数据,包括数据从哪里来,要到哪里去,传输的数据的单位是什么,要传多少数据,是一次传输还是循环传输等等。
1. 从哪里来到哪里去
我们知道DMA 传输数据的方向有三个:从外设到存储器,从存储器到外设,从存储器到存储器。具体的方向DMA_CCR 位4 DIR 配置:0 表示从外设到存储器,1 表示从存储器到外设。这里面涉及到的外设地址由DMA_CPAR 配置,存储器地址由DMA_CMAR配置。
外设到存储器
当我们使用从外设到存储器传输时,以ADC 采集为例。DMA 外设寄存器的地址对应的就是ADC 数据寄存器的地址,DMA 存储器的地址就是我们自定义的变量(用来接收存储AD 采集的数据)的地址。方向我们设置外设为源地址。
存储器到外设
当我们使用从存储器到外设传输时,以串口向电脑端发送数据为例。DMA 外设寄存器的地址对应的就是串口数据寄存器的地址,DMA 存储器的地址就是我们自定义的变量(相当于一个缓冲区,用来存储通过串口发送到电脑的数据)的地址。方向我们设置外设为目标地址。
存储器到存储器
当我们使用从存储器到存储器传输时,以内部FLASH 向内部SRAM 复制数据为例。DMA 外设寄存器的地址对应的就是内部FLASH(我们这里把内部FALSH 当作一个外设来看)的地址,DMA 存储器的地址就是我们自定义的变量(相当于一个缓冲区,用来存储来自内部FLASH 的数据)的地址。方向我们设置外设(即内部FLASH)为源地址。跟上面两个不一样的是,这里需要把DMA_CCR 位14:MEM2MEM:存储器到存储器模式配置为1,启动M2M模式。
2. 要传多少,单位是什么
当我们配置好数据要从哪里来到哪里去之后,我们还需要知道我们要传输的数据是多少,数据的单位是什么。以串口向电脑发送数据为例,我们可以一次性给电脑发送很多数据,具体多少由DMA_CNDTR 配置,这是一个32 位的寄存器,一次最多只能传输65535 个数据。要想数据传输正确,源和目标地址存储的数据宽度还必须一致,串口数据寄存器是8位的,所以我们定义的要发送的数据也必须是8 位。外设的数据宽度由DMA_CCRx 的PSIZE[1:0]配置,可以是8/16/32 位,存储器的数据宽度由DMA_CCRx 的MSIZE[1:0]配置,可以是8/16/32 位。
在DMA 控制器的控制下,数据要想有条不紊的从一个地方搬到另外一个地方,还必须正确设置两边数据指针的增量模式。外设的地址指针由DMA_CCRx 的PINC 配置,存储器的地址指针由MINC 配置。以串口向电脑发送数据为例,要发送的数据很多,每发送完一个,那么存储器的地址指针就应该加1,而串口数据寄存器只有一个,那么外设的地址指针就固定不变。具体的数据指针的增量模式由实际情况决定。
3. 什么时候传输完成
数据什么时候传输完成,我们可以通过查询标志位或者通过中断的方式来鉴别。每个DMA 通道在DMA 传输过半、传输完成和传输错误时都会有相应的标志位,如果使能了该类型的中断后,则会产生中断。有关各个标志位的详细描述请参考DMA 中断状态寄存器DMA_ISR 的详细描述。
传输完成还分两种模式,是一次传输还是循环传输,一次传输很好理解,即是传输一次之后就停止,要想再传输的话,必须关断DMA 使能后再重新配置后才能继续传输。循环传输则是一次传输完成之后又恢复第一次传输时的配置循环传输,不断的重复。具体的由DMA_CCRx 寄存器的CIRC 循环模式位控制。
|