I2S配置如下:
给它配置上DMA
当使用双缓冲DMA函数HAL_DMAEx_MultiBufferStart_IT之前需要设置如下回调函数:
hdma_spi3_tx.XferCpltCallback = spi3M0CpltCallback;
hdma_spi3_tx.XferM1CpltCallback = spi3M1CpltCallback;
hdma_spi3_tx.XferErrorCallback = spi3XferErrorCallback;
不会启动DMA,不设的画会直接报错返回。同时需要手动启动I2S以及开启它的时钟
代码如下:
int16_t sinTable[11][2]={
0, 0,
29771, 29771,
24874, 24874,
-8987, -8987,
-32383, -32383,
-18071, -18071,
17285, 17285,
32513, 32513,
9881, 9881,
-24257, -24257,
-30148, -30148,
};
void playSinWave(void)
{
__HAL_DMA_DISABLE(&hdma_spi3_tx); //ֹ֮ͣǰµÄ²¥·Å
HAL_DMA_Abort_IT(&hdma_spi3_tx);
HAL_DMA_Init(&hdma_spi3_tx);
//HAL_DMAEx_MultiBufferStart_IT(&hdma_spi3_tx, (uint32_t)audio_buf[0], (uint32_t)&hi2s3.Instance->DR, (uint32_t)audio_buf[1], AUDIO_MAX_POINTS / 2);
//HAL_I2S_Transmit_DMA(&hi2s3, audioDev.i2sBuf0, audioDev.audioRcvedLen);
//ÒòΪÎÒÃÇÊÇ16λµÄÒôƵ
/* Check if the I2S is already enabled */
if((hi2s3.Instance->I2SCFGR &SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE)
{
/* Enable I2S peripheral */
__HAL_I2S_ENABLE(&hi2s3);
}
/* Check if the I2S Tx request is already enabled */
if((hi2s3.Instance->CR2 & SPI_CR2_TXDMAEN) != SPI_CR2_TXDMAEN)
{
/* Enable Tx DMA Request */
SET_BIT(hi2s3.Instance->CR2, SPI_CR2_TXDMAEN);
}
HAL_DMAEx_MultiBufferStart_IT(&hdma_spi3_tx, (uint32_t)sinTable, (uint32_t)&hi2s3.Instance->DR, (uint32_t)(sinTable + 6), 11);
}
为了产生周期性的正弦波,sinTable的最后一个和第一个是相同的,因此这里是11个采样点。另外调用HAL_DMAEx_MultiBufferStart_IT时的第二个参数是正弦表的起始地址,第二个是总采样点数的一半 的地址,双声道16位采样时,DMA传输的一个单位是两个short的数据。上面代码中的调用由于是二维数组所以是加6,如果是一维数组,如下则要加12
int16_t sinTable[]={
0, 0,
29771, 29771,
24874, 24874,
-8987, -8987,
-32383, -32383,
-18071, -18071,
17285, 17285,
32513, 32513,
9881, 9881,
-24257, -24257,
-30148, -30148,
0, 0,
};
HAL_DMAEx_MultiBufferStart_IT(&hdma_spi3_tx, (uint32_t)sinTable, (uint32_t)&hi2s3.Instance->DR, (uint32_t)(sinTable + 12), 11);