本帖最后由 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);
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
一周热门 更多>