请教下,开启 i2s dma 单缓冲 后一直处于忙状态 ?

2019-07-20 11:49发布

本帖最后由 hpdell 于 2017-9-25 10:21 编辑

请教下,开启 i2s dma 单缓冲 后一直处于忙状态 ?

配置代码如下:下面的这个配置函数可以通过

/*
******************************************************************************************
* 函数名称:AVI_AUDIO_TX_DMA_Init
* 函数功能:SAIA TX DMA配置, 设置为双缓冲模式,并开启DMA传输完成中断
* 参数:    @:
*           buf0:  M0AR地址.
*           num:   每次传输数据量
*           _SAI_Width: 位宽(存储器和外设,同时设置),0,8位;1,16位;2,32位;
* 返回值:  无
******************************************************************************************
*/
static void AVI_AUDIO_TX_DMA_Init(u8* buf0,  u16 num, _SAI_DMA_WidthTypeDef _SAI_Width)
{
  u32 memwidth=0,perwidth=0;      //外设和存储器位宽
  switch(_SAI_Width)
  {
    case SAI_DMA_WIDTH_8BIT:         //8位
        memwidth = DMA_MDATAALIGN_BYTE;
        perwidth = DMA_PDATAALIGN_BYTE;
        break;
    case SAI_DMA_WIDTH_16BIT:         //16位
        memwidth = DMA_MDATAALIGN_HALFWORD;
        perwidth = DMA_PDATAALIGN_HALFWORD;
        break;
    case SAI_DMA_WIDTH_32BIT:         //32位
        memwidth = DMA_MDATAALIGN_WORD;
        perwidth = DMA_PDATAALIGN_WORD;
        break;
  }
  __HAL_RCC_DMA2_CLK_ENABLE();                                    //使能DMA2时钟

  SAI1_TXDMA_Handler.Instance = SAIA_TX_DMA2_StreamX;             //DMA2数据流3               
  SAI1_TXDMA_Handler.Init.Channel = SAIA_TX_DMA_CHANNEL_X;        //通道0
  SAI1_TXDMA_Handler.Init.Direction = DMA_MEMORY_TO_PERIPH;       //存储器到外设模式
  SAI1_TXDMA_Handler.Init.PeriphInc = DMA_PINC_DISABLE;           //外设非增量模式
  SAI1_TXDMA_Handler.Init.MemInc = DMA_MINC_ENABLE;               //存储器增量模式
  SAI1_TXDMA_Handler.Init.PeriphDataAlignment = perwidth;         //外设数据长度:16/32位
  SAI1_TXDMA_Handler.Init.MemDataAlignment = memwidth;            //存储器数据长度:16/32位
  SAI1_TXDMA_Handler.Init.Mode = DMA_CIRCULAR;                    //使用循环模式
  SAI1_TXDMA_Handler.Init.Priority = DMA_PRIORITY_HIGH;           //高优先级
  SAI1_TXDMA_Handler.Init.FIFOMode = DMA_FIFOMODE_DISABLE;        //不使用FIFO
  SAI1_TXDMA_Handler.Init.MemBurst = DMA_MBURST_SINGLE;           //存储器单次突发传输
  SAI1_TXDMA_Handler.Init.PeriphBurst = DMA_PBURST_SINGLE;        //外设突发单次传输

  __HAL_LINKDMA(&SAI1A_Handler,hdmatx,SAI1_TXDMA_Handler);        //将DMA与SAI联系起来
  HAL_DMA_DeInit(&SAI1_TXDMA_Handler);                            //先清除以前的设置
  HAL_DMA_Init(&SAI1_TXDMA_Handler);                                    //初始化DMA


  //在开启DMA之前先使用__HAL_UNLOCK()解锁一次DMA,因为HAL_DMA_Statrt()HAL_DMAEx_MultiBufferStart()
  //这两个函数一开始要先使用__HAL_LOCK()锁定DMA,而函数__HAL_LOCK()会判断当前的DMA状态是否为锁定状态,如果是
  //锁定状态的话就直接返回HAL_BUSY,这样会导致函数HAL_DMA_Statrt()和HAL_DMAEx_MultiBufferStart()后续的DMA配置
  //程序直接被跳过!DMA也就不能正常工作,为了避免这种现象,所以在启动DMA之前先调用__HAL_UNLOC()先解锁一次DMA。
  __HAL_UNLOCK(&SAI1_TXDMA_Handler);  


  HAL_DMA_Start(&SAI1_TXDMA_Handler,(u32)buf0, (u32)&SAI1_Block_A->DR, num);


  __HAL_DMA_DISABLE(&SAI1_TXDMA_Handler);                         //先关闭DMA
  HAL_Delay(1);                                //最少延时10us延时,防止-O2优化出问题,目前设置为1ms
  __HAL_DMA_ENABLE_IT(&SAI1_TXDMA_Handler,DMA_IT_TC);             //开启传输完成中断
  __HAL_DMA_CLEAR_FLAG(&SAI1_TXDMA_Handler,SAIA_TX_DMA_FLAG_TCIF_X);     //清除DMA传输完成中断标志位
  HAL_NVIC_SetPriority(SAIA_TX_DMA2_StreamX_IRQn, 1, 0);        //DMA中断优先级
  HAL_NVIC_EnableIRQ(SAIA_TX_DMA2_StreamX_IRQn);

//  __HAL_DMA_ENABLE(&SAI1_TXDMA_Handler);
}




下面这个函数是在程序运行时进行数据发送的

_addr  需要发送数据的缓冲地址
_size 发送数据大小
目前就是使用这个函数时会提示忙而返回
void  SAI_TranConfig(uint32_t _addr, uint32_t _size)
{

  HAL_DMA_Start(&SAI1_TXDMA_Handler, _addr, (u32)&SAI1_Block_A->DR, _size);
}













友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。