DMA播放速度慢的STM32 I2S

DMA播放速度慢的STM32 I2S,stm32,spi,dma,fatfs,i2s,Stm32,Spi,Dma,Fatfs,I2s,我想用STM32实现一个WAV/MP3播放器(现在让我们说WAV),它用FATFS从SD读取它,然后用DMA将它传输到I2S缓冲区 问题是,当我插上扬声器时,它会以正确的音调(音调)播放歌曲,但播放速度非常慢,而且还会发出奇怪的重复滴答声,就像缓冲区被慢慢填满,或者播放速度缓慢,但频率正确 我将STM32_F4VE(STM32F407VET6)与PCM5102一起使用(只需要数据、16位的32xfs的BCK和fs的LRCK) 这里我附上几个代码部分: main.c wavplayer.c

我想用STM32实现一个WAV/MP3播放器(现在让我们说WAV),它用FATFS从SD读取它,然后用DMA将它传输到I2S缓冲区

问题是,当我插上扬声器时,它会以正确的音调(音调)播放歌曲,但播放速度非常慢,而且还会发出奇怪的重复滴答声,就像缓冲区被慢慢填满,或者播放速度缓慢,但频率正确

我将STM32_F4VE(STM32F407VET6)与PCM5102一起使用(只需要数据、16位的32xfs的BCK和fs的LRCK)

这里我附上几个代码部分: main.c

wavplayer.c

    /**
 * @brief Select WAV file to play
 * @retval returns true when file is found in USB Drive
 */
bool wavPlayer_fileSelect(const char* filePath)
{
  UINT readBytes = 0;
  //Open WAV file
  if(f_open(&wavFile, filePath, FA_READ) != FR_OK)
  {
    return false;
  }
  //Read WAV file Header
  f_read(&wavFile, &wavHeader, sizeof(wavHeader), &readBytes);
  sprintf(UART_buff, "Tamaño del archivo: %d\n\rFrecuencia de muestreo: %d\n\r", wavHeader.FileSize, wavHeader.SampleRate);
  HAL_UART_Transmit_IT(&huart1, UART_buff, strlen(UART_buff));//TX Function
  end_of_file_reached = false;
  return true;
}

/**
 * @brief WAV File Play
 */
void wavPlayer_play(void)
{
  isFinished = false;
  //Read Audio data from USB Disk
  f_lseek(&wavFile, 0);
  f_read (&wavFile, &audioBuffer[0], AUDIO_BUFFER_SIZE, &playerReadBytes);
  audioRemainSize = wavHeader.FileSize - playerReadBytes;
  //Start playing the WAV
  HAL_I2S_Transmit_DMA(&hi2s2, (uint16_t *)&audioBuffer[0], AUDIO_BUFFER_SIZE);
}

    
/**
 * @brief Half/Full transfer Audio callback for buffer management
 */
void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s)
{
  if(hi2s->Instance == SPI2)
  {
      if(end_of_file_reached){
                return;
        }

        res = f_read (&wavFile, &audioBuffer[AUDIO_BUFFER_SIZE/2], AUDIO_BUFFER_SIZE/2, &playerReadBytes);

        if(audioRemainSize > (AUDIO_BUFFER_SIZE / 2))
        {
          audioRemainSize -= playerReadBytes;
        }
        else
        {
          audioRemainSize = 0;
          end_of_file_reached = true;
        }
  }
}

void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
{
  if(hi2s->Instance == SPI2)
  {
      if(end_of_file_reached){
          return;
      }

      res = f_read (&wavFile, &audioBuffer[0], AUDIO_BUFFER_SIZE/2, &playerReadBytes);

      if(audioRemainSize > (AUDIO_BUFFER_SIZE / 2))
      {
          audioRemainSize -= playerReadBytes;
      }
      else
      {
          audioRemainSize = 0;
          end_of_file_reached = true;
      }
  }
}

我的第一个猜测是让UART也在DMA模式下工作。您是否测量过I2S信号的实际输出时钟或UART的波特率?您还可以提供I2S序列的初始化吗?我的第一个猜测是让UART也在DMA模式下工作。您是否测量过I2S信号的实际输出时钟或UART的波特率?您还可以提供I2S序列的初始化吗?
    /**
 * @brief Select WAV file to play
 * @retval returns true when file is found in USB Drive
 */
bool wavPlayer_fileSelect(const char* filePath)
{
  UINT readBytes = 0;
  //Open WAV file
  if(f_open(&wavFile, filePath, FA_READ) != FR_OK)
  {
    return false;
  }
  //Read WAV file Header
  f_read(&wavFile, &wavHeader, sizeof(wavHeader), &readBytes);
  sprintf(UART_buff, "Tamaño del archivo: %d\n\rFrecuencia de muestreo: %d\n\r", wavHeader.FileSize, wavHeader.SampleRate);
  HAL_UART_Transmit_IT(&huart1, UART_buff, strlen(UART_buff));//TX Function
  end_of_file_reached = false;
  return true;
}

/**
 * @brief WAV File Play
 */
void wavPlayer_play(void)
{
  isFinished = false;
  //Read Audio data from USB Disk
  f_lseek(&wavFile, 0);
  f_read (&wavFile, &audioBuffer[0], AUDIO_BUFFER_SIZE, &playerReadBytes);
  audioRemainSize = wavHeader.FileSize - playerReadBytes;
  //Start playing the WAV
  HAL_I2S_Transmit_DMA(&hi2s2, (uint16_t *)&audioBuffer[0], AUDIO_BUFFER_SIZE);
}

    
/**
 * @brief Half/Full transfer Audio callback for buffer management
 */
void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s)
{
  if(hi2s->Instance == SPI2)
  {
      if(end_of_file_reached){
                return;
        }

        res = f_read (&wavFile, &audioBuffer[AUDIO_BUFFER_SIZE/2], AUDIO_BUFFER_SIZE/2, &playerReadBytes);

        if(audioRemainSize > (AUDIO_BUFFER_SIZE / 2))
        {
          audioRemainSize -= playerReadBytes;
        }
        else
        {
          audioRemainSize = 0;
          end_of_file_reached = true;
        }
  }
}

void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
{
  if(hi2s->Instance == SPI2)
  {
      if(end_of_file_reached){
          return;
      }

      res = f_read (&wavFile, &audioBuffer[0], AUDIO_BUFFER_SIZE/2, &playerReadBytes);

      if(audioRemainSize > (AUDIO_BUFFER_SIZE / 2))
      {
          audioRemainSize -= playerReadBytes;
      }
      else
      {
          audioRemainSize = 0;
          end_of_file_reached = true;
      }
  }
}