|
|

楼主 |
发表于 2025-11-26 10:40:25
|
显示全部楼层
另外HAL的外设DMA默认不支持双缓冲,感觉挺坑人的,手动调用DMA的双缓冲设计函数又跟外设函数的DMA冲突,只能手动操作寄存器实现(WM8978.c中发送函数下的部分注释代码)
不过目前读取wav直接扔给I2S播放还是会存在缓冲区边界破音问题,目前还没找到原因究竟在哪
int fatfs_readbuffer(FIL *file,void * buffer,unsigned int size)
{
FRESULT res;
int cnt=0;
int bw=0;
while (1) {
res = f_read(file, buffer+cnt,size-cnt,&bw);
if(res!=FR_OK)
{
return -1;
}
cnt += bw;
if(bw==0)
{
return -2;
}
if (size != cnt) {
//DBGOUT("ReadError@%s: %d\n", __func__, __LINE__);
//UART_DUMP(&g_frame_rx);
continue;
}
//count = nbytes = 0;
break;
}
return 0;
}
// DMA 回调函数
void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hspi) {
// 处理缓冲区切换后的操作
// 更新 buffer0 或 buffer1 的数据
//printf("b\n");
//LL_DMA_ClearFlag_FE0(DMA1_Stream0);
__HAL_I2S_CLEAR_UDRFLAG(&hi2s3);
xSemaphoreGiveFromISR(wav_semap,pdTRUE);
}
int wav_thread(char* filename)
{
FIL file;
FRESULT res;
int bw;
char bufferflag=0;
wav_semap=xSemaphoreCreateBinary();
res=f_open(&file,filename,FA_OPEN_EXISTING | FA_READ);
if(res!=FR_OK)
{
printf("fatfs open error:%d\n",res);
//vTaskDelete(NULL);
}
printf("open file success\n");
res=f_read(&file,&wavheader,sizeof(wavheader),&bw);
if(res!=FR_OK)
{
printf("fatfs read error:%d\n",res);
}
printf("rid:%x\n",wavheader.rId);
printf("rLen:%x\n",wavheader.rLen);
printf("fLen:%x\n",wavheader.fLen);
printf("Format:%x\n",wavheader.wFormatTag);
printf("nChannels:%x\n",wavheader.nChannels);
printf("Samplerate:%x\n",wavheader.nSamplesPerSec);
printf("BitsPerSample:%x\n",wavheader.wBitsPerSample);
fatfs_readbuffer(&file,wav_buffer1,65535*4);
fatfs_readbuffer(&file,wav_buffer2,65535*4);
// res=f_read(&file,wav_buffer2,65535,&bw);
// if(res!=FR_OK)
// {
// printf("fatfs read wav error:%d\n",res);
// }
LL_DMA_DisableFifoMode(DMA1,LL_DMA_STREAM_0);
LL_DMA_DisableIT_FE(DMA1,LL_DMA_STREAM_0);
HAL_DMAEx_MultiBufferStart_IT((hi2s3.hdmatx),
(uint32_t)wav_buffer1,
(uint32_t)&(SPI3->TXDR),
(uint32_t)wav_buffer2,
65535);
LL_DMA_DisableStream(DMA1,LL_DMA_STREAM_0);
LL_DMA_DisableIT_FE(DMA1,LL_DMA_STREAM_0);
LL_DMA_DisableIT_HT(DMA1,LL_DMA_STREAM_0);
LL_DMA_DisableIT_TE(DMA1,LL_DMA_STREAM_0);
LL_DMA_DisableIT_DME(DMA1,LL_DMA_STREAM_0);
LL_DMA_EnableStream(DMA1,LL_DMA_STREAM_0);
// HAL_I2S_Transmit_DMA(&hi2s3,wav_buffer1,65535);
// hi2s3.hdmatx->XferCpltCallback = HAL_I2S_TxCpltCallback;
// hi2s3.State = HAL_I2S_STATE_BUSY_TX;
// hi2s3.ErrorCode = HAL_I2S_ERROR_NONE;
//
// LL_DMA_EnableIT_TC(DMA1,LL_DMA_STREAM_0);
// LL_DMA_EnableStream(DMA1,LL_DMA_STREAM_0);
SET_BIT(hi2s3.Instance->CFG1, SPI_CFG1_TXDMAEN);
SET_BIT(hi2s3.Instance->CR1, SPI_CR1_SPE);
SET_BIT(hi2s3.Instance->CR1, SPI_CR1_CSTART);
while(1)
{
if(xSemaphoreTake(wav_semap, 1000)!=pdTRUE)
{
printf("semp error\n");
}
if(bufferflag==0)
{
// HAL_I2S_Transmit_DMA(&hi2s3,wav_buffer2,65535);
fatfs_readbuffer(&file,wav_buffer1,65535*4);
// res=f_read(&file,wav_buffer1,65535,&bw);
// if(res!=FR_OK)
// {
// printf("fatfs read wav error:%d\n",res);
// }
bufferflag=1;
}
else
{
// __HAL_I2S_CLEAR_UDRFLAG(&hi2s3);
// HAL_I2S_Transmit_DMA(&hi2s3,wav_buffer1,65535);
fatfs_readbuffer(&file,wav_buffer2,65535*4);
// res=f_read(&file,wav_buffer2,65535,&bw);
// if(res!=FR_OK)
// {
// printf("fatfs read wav error:%d\n",res);
// }
bufferflag=0;
}
//printf("a\n");
}
} |
|