DMA 双缓冲模式

双缓冲区模式

此模式可用于所有 DMA1 和 DMA2 数据流。
1:除了有两个存储器指针之外,双缓冲区数据流的工作方式与常规(单缓冲区)数据流的一样。
2:使能双缓冲区模式时,将自动使能循环模式,并在每次事务结束时交换存储器指针。
3:每次事务结束时, DMA 控制器都从一个存储器目标交换为另一个存储器目标,软件 在处理一个存储器区域的同时, DMA 传输还可以填充/使用第二个存储器区域。
4:由于存储器到存储器模式与循环模式不兼容,所以当使能双缓冲区模式时,不允许配置存储器到存储器模式。

基于DMA双缓冲模式的的特点,应用中必须开辟两个存储区以及存放两个存储区首地址的存储寄存器,DMA_SxM0AR和DMA_SxM1AR。
1:DMA_SxM0AR:指向存储区0(DMA_Memory_0),单缓冲模式下默认使用该寄存器做存储区指针。
2:DMA_SxM1AR:指向存储区1(DMA_Memory_1),仅在DMA双缓冲模式下才能使用。
3:DMA正在访问的当前存储区由DMA_SxCR表示
CT:当前目标
CT = 0:DMA正在访问存储区0,CPU可以访问存储区1
CT = 1:DMA正在访问存储区1,CPU可以访问存储区0
好处:
使用DMA双缓冲传输,既可以减少CPU的负荷,又能最大程度地实现DMA数据传输和CPU数据处理互不打扰又互不耽搁,DMA双缓冲模式的循环特性,使用它对存储区的空间容量要求也会大大降低。尤其在大批量数据传送时,你只需开辟两个合适大小的存储区,能满足DMA在切换存储区时的当前新存储区空出来就好,并不一定要开辟多大多深的存储空间,单纯一味地加大双缓冲区的深度并不明显改善数据传输状况。

配置

1:开辟两个缓冲区
#define DMA_Meo_Size 100
u8 Buffer0[DMA_Meo_Size]={0x00};
u8 Buffer1[DMA_Meo_Size]={0x00};


2:配置双缓冲模式
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  
//其余和单缓冲模式一样
//内存0 即Buffer0先被传输
DMA_DoubleBufferModeConfig(DMA2_Stream1,(uint32_t)&Buffer1,DMA_Memory_0);
DMA_DoubleBufferModeCmd(DMA2_Stream1,ENABLE);

在每个缓冲区满了后会产生传输完成中断
硬件自动切换缓冲区。

3:根据CT标志查看DMA正在访问哪一个缓冲区

/**
  * @brief  Returns the current memory target used by double buffer transfer.
  * @param  DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0
  *          to 7 to select the DMA Stream.
  * @retval The memory target number: 0 for Memory0 or 1 for Memory1. 
  */
uint32_t DMA_GetCurrentMemoryTarget(DMA_Stream_TypeDef* DMAy_Streamx)
{
  uint32_t tmp = 0;

  /* Check the parameters */
  assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx));

  /* Get the current memory target */
  if ((DMAy_Streamx->CR & DMA_SxCR_CT) != 0)
  {
    /* Current memory buffer used is Memory 1 */
    tmp = 1;
  }  
  else
  {
    /* Current memory buffer used is Memory 0 */
    tmp = 0;    
  }
  return tmp;
}

DMA_GetCurrentMemoryTarget(DMA2_Stream1);
如果返回值为1,说明DMA正在访问缓冲区1,则CPU可以访问缓冲区0的数据
if(DMA_GetCurrentMemoryTarget(DMA2_Stream1) == 1)

猜你喜欢

转载自blog.csdn.net/qq_19999465/article/details/81054680
DMA
今日推荐