单片机中DMA的配置

DMA(Direct Memory Access,直接内存访问)是一种无需CPU直接参与的数据传输机制。

寄存器->外设    外设->外设

外设->寄存器    寄存器->寄存器

DMA可以实现寄存器与外设之间的相互传输。那么什么是寄存器,什么是外设?

对于DMA而言,寄存器的概念是:片上flash、外设eeprom、外设flash等。外设的概念是:UART、IIC、SPI等。

以莱智单片机GW32L0xx为例:

void uf_DMA_UartTxReqInit(void)
{
  DMA_InitTypeDef DMA_InitStruct;
  
  CMU_APBPeriph0ClockCmd(CMU_APBPeriph0_DMA, ENABLE);
  
  DMA_StructInit(&DMA_InitStruct);
  DMA_InitStruct.DMA_SrcAddr = (uint32_t)RxBuffer;           //源地址
  DMA_InitStruct.DMA_DstAddr = (uint32_t)&(UART_1->TXR);    //目标地址
  DMA_InitStruct.DMA_TransDir = DMA_TransDir_M2P;          //传输方向,寄存器->外设
  DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;              //传输模式,正常模式是单次传输
  DMA_InitStruct.DMA_SrcBurstLen = DMA_BurstLen_1;       //源突发传输长度,每次从源设备连续读取多少个数据,宽度与传输宽度一致
  DMA_InitStruct.DMA_DstBurstLen = DMA_BurstLen_1;        //目标突发传输长度,每次对目标设备连续发送多少个数据
  DMA_InitStruct.DMA_SrcAddrDir = DMA_AddrDir_Inc;       //传输方向,递增
  DMA_InitStruct.DMA_DstAddrDir = DMA_AddrDir_Hold;	     //传输方向,不变
  DMA_InitStruct.DMA_SrcTransDataSize = DMA_TransDataSize_8Bits;
  DMA_InitStruct.DMA_DstTransDataSize = DMA_TransDataSize_8Bits;    //传输宽度
  DMA_InitStruct.DMA_TransBlkSize = 1024;	     //传输块大小,最大4095
  DMA_InitStruct.DMA_SrcHandShakeSel = DMA_HandShakeSel_SoftWare;    //软件等待
  DMA_InitStruct.DMA_DstHandShakeSel = DMA_HandShakeSel_HardWare;   //硬件等待
  DMA_InitStruct.DMA_Priority = DMA_Priority_Low;	          //传输优先级
  DMA_InitStruct.DMA_DstPerReq = 0x0;                //外设请求源编号,0是TXD1,1是RXD1
  DMA_InitStruct.DMA_DstPerHandShakeInput = DMA_PerHandShakeInput_HS0;   //指定硬件握手接口(0~3)给通道0/1的目标外设
  DMA_Init(DMA_ChannelSel_CH0, &DMA_InitStruct);    //若源通道和目标通道合并为一个,则每次传输前需进行初始化,若单独通道则不用
  
  DMA_ITConfig(DMA_ChannelSel_CH0, DMA_ITFlag_BlkTc, ENABLE);   //DMA块传输完成中断,当DMA向目标外设的块传输完成时,产生中断
  
  DMA_Cmd(DMA_ChannelSel_CH0, DISABLE);	
}

我们依次需要初始化源地址、目标地址、传输方向(M指寄存器,P指外设)、传输模式(正常模式Normal、源聚合Gather、目标散列Scatter模式)、源突发传输长度目标突发传输长度、传输方向(递增、递减、不变)、传输宽度(字节、半字、字)、块传输大小、等待方式(寄存器-软件等待,外设-硬件等待)、传输优先级(低、高)、外设请求源编号、指定硬件握手接口。

莱智单片机的DMA共有2个通道,4个硬件外设接口。如果源通道和目标通道合并为一个,则每次传输前需重新初始化,如果分开两个通道,则只需初始化一遍即可。

另外值得注意的是Gather/Scatter功能

在传统的 DMA 传输数据的过程中,要求源物理地址和目标物理地址必须是连续的。如果物理上不是连续的,则DMA传输要分成多次完成。当传输完一块物理连续的数据后,生成一个中断通知CPU 进行下一次传输, 这种方式需要多次中断。

Scatter 功能是相对于目标外设传输而言的。在一次块传输中,从一个通道读取的数据分散的写到多个物 理上不连续的目标外设地址。Gather 功能是相对于源外设传输而言的,在一次块传输中,将多个分散在源外设不连续物理地址里面的 数据按照顺序发送到一个通道。

其中块传输大小、源突发传输长度、目标突发传输长度的含义是什么?

1. 块传输大小:它是每个DMA传输中处理的数据量。它与数据的宽度(字节、半字、字等)一致,表示每次传输的数据大小。例如,如果数据宽度为字节,块传输大小为4095,则每次传输会处理4095个字节的数据。

2. 源突发传输长度:它是从源外设读取数据时的突发传输长度。突发传输是指DMA在一次传输中一次性连续读取多个数据。源突发传输长度表示每次从源外设读取的数据量。例如,如果源突发传输长度为8,则每次从源外设读取8个数据。

3. 目标突发传输长度:它是向目标地址空间写入数据时的突发传输长度。类似于源突发传输长度,目标突发传输长度表示每次向目标地址写入的数据量。例如,如果目标突发传输长度为16,则每次写入16个数据到目标地址。

那么为什么需要定义这三个参数?不定义块传输长度会不会有影响?

块传输大小则是用来限制每个DMA传输中总共要处理的数据量。它可以作为对传输大小的额外限制,以避免超出DMA控制器或目标设备的处理能力。

举个例子,假设有一个外设,每次最多可以进行8个字节的突发读取或写入,但是我们需要传输4095个字节的数据。如果只设置源突发传输长度和目标突发传输长度,那么每次只能传输8个字节,需要进行512次传输才能完成。这样的话,传输的效率就会非常低下。 通过设置块传输大小为4095,我们可以告诉DMA控制器,每次传输总共处理4095个字节的数据。然后,DMA控制器会自动根据外设的突发传输长度限制,将4095个字节的数据分为多个突发传输进行。这样,可以大大提高传输效率,减少传输的次数。

以上是我个人的一些理解与看法,欢迎批评指正!

  • 27
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值