cancel
Showing results for 
Search instead for 
Did you mean: 

Crack at the end of I2S tranmission via DMA on STM32L073

JSchu.5
Associate II

I'm running a STM32L073 to generate a sine wave tone via I2S in normal DMA mode. The amplifier is a MAX98357A. The MODE pin is connected to VDD so only left channel is considered. I2S runs at 48kHz and the uC clock source is internal. The output tone itself sounds fine but at the end of transmission I always hear a crack. My first thought was that the last sample of the generated sine is not 0 but it is. So I added a zero period to the end of the tone without any improvement. Finally I just output a zero tone causing the same crack after the transmission. Does anyone have an idea what's going on?

This is the cube generated code

hi2s2.Instance = SPI2;
  hi2s2.Init.Mode = I2S_MODE_MASTER_TX;
  hi2s2.Init.Standard = I2S_STANDARD_PHILIPS;
  hi2s2.Init.DataFormat = I2S_DATAFORMAT_16B;
  hi2s2.Init.MCLKOutput = I2S_MCLKOUTPUT_DISABLE;
  hi2s2.Init.AudioFreq = I2S_AUDIOFREQ_48K;
  hi2s2.Init.CPOL = I2S_CPOL_LOW;

The DMA Config

hdma_spi2_tx.Instance = DMA1_Channel5;
    hdma_spi2_tx.Init.Request = DMA_REQUEST_2;
    hdma_spi2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_spi2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi2_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_spi2_tx.Init.Mode = DMA_NORMAL;
    hdma_spi2_tx.Init.Priority = DMA_PRIORITY_LOW;
    if (HAL_DMA_Init(&hdma_spi2_tx) != HAL_OK)

Play the zero tone. Minimal version of my code without any error checking.

int16_t zero[240] = {0};
uint32_t playSampleCnt = 0;
uint32_t sampleCntTimeout = 0;
 
void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s)
{
    playSampleCnt += 240;
    
    //Start new tone if timeout not expired
    if(sampleCntTimeout == 0 || playSampleCnt < sampleCntTimeout)
        HAL_I2S_Transmit_DMA (&hi2s2, (uint16_t*)zero, 240); //120 left 120 right
}
 
void playGeneratedTone(void)
{
        //120 left 120 right
        HAL_I2S_Transmit_DMA (&hi2s2, (uint16_t*)zero, 240)
       sampleCntTimeout = 48 * 100;
       playSampleCnt  = 0;
}

1 REPLY 1
MM..1
Chief III

Your crack is normal on big amount of DACs. Because when I2S end it stops data and too stops LRCK and BCK and if used MCK, this result on DAC chip to unhandled exception and crack.

Then normal steps is set circular DMA ... unmute DAC .... mute DAC .... stop circular DMA .... power off

On real I2S bus never can nothing stop, only data can be zero.