cancel
Showing results for 
Search instead for 
Did you mean: 

How to read PDM microphone with the Serial Audio Interface(SAI)

nlbutts
Associate II

I have a really simple application setup. I'm currently feeding in one PDM microphone. I'm using the SAI interface (code is attached). First there appears to be a bug in the ST code. The SAI_PDMCR register have a field to set up to 4 microphones (see reference manual).

The STM32CubeMX doesn't allow you to set the value to anything other than a 3. If you set it to a 4, this assert will fail:

#define IS_SAI_PDM_MIC_PAIRS_NUMBER(VALUE)   ((1U <= (VALUE)) && ((VALUE) <= 3U))

But the code that sets the register is shown here (line 759 of stm32h7xx_hal_sai.c)

SaiBaseAddress->PDMCR = (hsai->Init.PdmInit.ClockEnable | ((hsai->Init.PdmInit.MicPairsNbr - 1U) << SAI_PDMCR_MICNBR_Pos));

So you can never enable the 4th microphone pair. My next problem is I never receive any PDM data. I can see the clock coming out of the SAI clock pin (although the clock makes no sense from what I tried to set).

I then call :

HAL_SAI_Receive_IT(&hsai_BlockA1, audioData, 48000);

and set a breakpoint into the PDM interrupt. But the interrupt is never called. I'm at a bit of a loss. Looking at the SAI status register, the FIFO is always empty.

I'm attaching the example project.

2 REPLIES 2
KnarfB
Principal III

The app note might help: AN5027 Application note "Interfacing PDM digital microphones using STM32 MCUs and MPUs". And there is a support library: UM2372 User manual "STM32Cube PDM2PCM software library for the STM32F4/F7/H7 Series"

nlbutts
Associate II

Thanks for the suggestion. Yeah I had read through that app note. Here is what I've found since I posted:

1) The Slot Active needs to be set to all, that at least caused the interrupt to fire

2) The interrupt isn't properly by the autocode generation. I would expect a call to the interrupt handler function, but it didn't generate one.

/**
 
  * @brief This function handles SAI1 global interrupt.
 
  */
 
void SAI1_IRQHandler(void)
 
{
 
  /* USER CODE BEGIN SAI1_IRQn 0 */
 
  /* USER CODE END SAI1_IRQn 0 */
 
  /* USER CODE BEGIN SAI1_IRQn 1 */
 
  /* USER CODE END SAI1_IRQn 1 */
 
}