cancel
Showing results for 
Search instead for 
Did you mean: 

Problem with microphone MP34DT05TR on SAI1 of STM32H750

DMast.1
Associate II

Good evening, I'm trying to interfacing a MEMS microphone MP34DT05TR in our board using interface SAI1 (SAI1_CK1 on PE1, SAI1_D1 on PD6). To get a faster result (I hoped!!) I used the cubemx to configure the interface and starting code. I see the clock and the (I suppose) the PDM signal on SAI1_D1 but in the following test code I read all zero in RxBuffer

int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SAI1_Init();
  /* USER CODE BEGIN 2 */
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
    HAL_SAI_Receive(&hsai_BlockA1, RxBuffer, 10, 100);
 
  }
  /* USER CODE END 3 */
}

Here is the initialization code:

void SystemClock_Config(void)

{

 RCC_OscInitTypeDef RCC_OscInitStruct = {0};

 RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

 /** Supply configuration update enable

 */

 HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);

 /** Configure the main internal regulator output voltage

 */

 __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

 while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}

 /** Initializes the RCC Oscillators according to the specified parameters

 * in the RCC_OscInitTypeDef structure.

 */

 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;

 RCC_OscInitStruct.HSEState = RCC_HSE_ON;

 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;

 RCC_OscInitStruct.PLL.PLLM = 4;

 RCC_OscInitStruct.PLL.PLLN = 400;

 RCC_OscInitStruct.PLL.PLLP = 2;

 RCC_OscInitStruct.PLL.PLLQ = 8;

 RCC_OscInitStruct.PLL.PLLR = 2;

 RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_1;

 RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;

 RCC_OscInitStruct.PLL.PLLFRACN = 0;

 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)

 {

   Error_Handler();

 }

 /** Initializes the CPU, AHB and APB buses clocks

 */

 RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK

                             |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2

                             |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;

 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

 RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;

 RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;

 RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;

 RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;

 RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;

 RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;

 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)

 {

   Error_Handler();

 }

}

static void MX_SAI1_Init(void)

{

 /* USER CODE BEGIN SAI1_Init 0 */

 /* USER CODE END SAI1_Init 0 */

 /* USER CODE BEGIN SAI1_Init 1 */

 /* USER CODE END SAI1_Init 1 */

 hsai_BlockA1.Instance = SAI1_Block_A;

 hsai_BlockA1.Init.Protocol = SAI_FREE_PROTOCOL;

 hsai_BlockA1.Init.AudioMode = SAI_MODEMASTER_RX;

 hsai_BlockA1.Init.DataSize = SAI_DATASIZE_8;

 hsai_BlockA1.Init.FirstBit = SAI_FIRSTBIT_MSB;

 hsai_BlockA1.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;

 hsai_BlockA1.Init.Synchro = SAI_ASYNCHRONOUS;

 hsai_BlockA1.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;

 hsai_BlockA1.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;

 hsai_BlockA1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;

 hsai_BlockA1.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_44K;

 hsai_BlockA1.Init.MonoStereoMode = SAI_MONOMODE;

 hsai_BlockA1.Init.CompandingMode = SAI_NOCOMPANDING;

 hsai_BlockA1.Init.PdmInit.Activation = ENABLE;

 hsai_BlockA1.Init.PdmInit.MicPairsNbr = 1;

 hsai_BlockA1.Init.PdmInit.ClockEnable = SAI_PDM_CLOCK1_ENABLE;

 hsai_BlockA1.FrameInit.FrameLength = 16;

 hsai_BlockA1.FrameInit.ActiveFrameLength = 1;

 hsai_BlockA1.FrameInit.FSDefinition = SAI_FS_STARTFRAME;

 hsai_BlockA1.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;

 hsai_BlockA1.FrameInit.FSOffset = SAI_FS_FIRSTBIT;

 hsai_BlockA1.SlotInit.FirstBitOffset = 0;

 hsai_BlockA1.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;

 hsai_BlockA1.SlotInit.SlotNumber = 2;

 hsai_BlockA1.SlotInit.SlotActive = 0x00000003;

 if (HAL_SAI_Init(&hsai_BlockA1) != HAL_OK)

 {

   Error_Handler();

 }

 /* USER CODE BEGIN SAI1_Init 2 */

 /* USER CODE END SAI1_Init 2 */

}

void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai)

{

 GPIO_InitTypeDef GPIO_InitStruct;

 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};

/* SAI1 */

   if(hsai->Instance==SAI1_Block_A)

   {

   /* Peripheral clock enable */

 /** Initializes the peripherals clock

 */

   PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1;

   PeriphClkInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLL;

   if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)

   {

     Error_Handler();

   }

   if (SAI1_client == 0)

   {

      __HAL_RCC_SAI1_CLK_ENABLE();

   }

   SAI1_client ++;

   /**SAI1_A_Block_A GPIO Configuration

   PE2    ------> SAI1_CK1

   PD6    ------> SAI1_D1

   */

   GPIO_InitStruct.Pin = GPIO_PIN_2;

   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

   GPIO_InitStruct.Pull = GPIO_NOPULL;

   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;

   GPIO_InitStruct.Alternate = GPIO_AF2_SAI1;

   HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

   GPIO_InitStruct.Pin = GPIO_PIN_6;

   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

   GPIO_InitStruct.Pull = GPIO_NOPULL;

   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;

   GPIO_InitStruct.Alternate = GPIO_AF2_SAI1;

   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

   }

}

After fix this problem, I would like to convert the input PDM data into PCM to check if the board "listen" something correct. How can I check this? Using an USB stick and creating an audio file? Is there a lib to convert PDM to PCM for the STM32H750?

Thanks in advance to anybody how can help me.

Regards,

D.M.

7 REPLIES 7
Imen.D
ST Employee

Hello @DMast.1​ ,

You can use ST PDM2PCM library within CubeH7 mcu package:

\STM32Cube_FW_H7_V1.9.0\Projects\STM32H750B-DK\Demonstrations\STemWin\Modules\audio_player\Addons\PDM

I adivse you to have a look at these resources : 

Hope this helps you ��!

Imen

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen
DMast.1
Associate II

Hi Imen,

thanks but my problem is before using the library to converto the PDM to PCM. As I wrote before, maybe an error on initialize of peripheral, because the HAL_SAI_Receive reads always 0.

Regards,

Renato

DMast.1
Associate II

Any suggestion?

DMast.1
Associate II

Finally something start works....now I get data from mic in polling, but I would like to enable the DMA. I initialize as below, I get the ISR but I don't get data on destination buffer (may be a wrong mic setup sequence)

int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
/* Configure the peripherals common clocks */
  PeriphCommonClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SAI1_Init();
  /* USER CODE BEGIN 2 */
  /* Start the process receive DMA */
  HAL_SAI_Receive_DMA(&hsai_BlockA1, RxBuffer, sizeof(RxBuffer));
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

Here is the SAI1 init (SAI1_CK1 on PE2, SAI1_D1 on PD6)

static void MX_SAI1_Init(void)
{
 
  /* USER CODE BEGIN SAI1_Init 0 */
 
  /* USER CODE END SAI1_Init 0 */
 
  /* USER CODE BEGIN SAI1_Init 1 */
 
  /* USER CODE END SAI1_Init 1 */
	hsai_BlockA1.Instance = SAI1_Block_A;
	hsai_BlockA1.Init.Protocol = SAI_FREE_PROTOCOL;
	hsai_BlockA1.Init.AudioMode = SAI_MODEMASTER_RX;
	hsai_BlockA1.Init.DataSize = SAI_DATASIZE_8;
	hsai_BlockA1.Init.FirstBit = SAI_FIRSTBIT_MSB;
	hsai_BlockA1.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
	hsai_BlockA1.Init.Synchro = SAI_ASYNCHRONOUS;
	hsai_BlockA1.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
	hsai_BlockA1.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
	hsai_BlockA1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;
	hsai_BlockA1.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_96K;//>>SAI_AUDIO_FREQUENCY_44K;
	hsai_BlockA1.Init.MonoStereoMode = SAI_MONOMODE;
	hsai_BlockA1.Init.CompandingMode = SAI_NOCOMPANDING;
	hsai_BlockA1.Init.PdmInit.Activation = ENABLE;
	hsai_BlockA1.Init.PdmInit.MicPairsNbr = 1;
	hsai_BlockA1.Init.PdmInit.ClockEnable = SAI_PDM_CLOCK1_ENABLE;
	hsai_BlockA1.FrameInit.FrameLength = 16;
	hsai_BlockA1.FrameInit.ActiveFrameLength = 1;
	hsai_BlockA1.FrameInit.FSDefinition = SAI_FS_STARTFRAME;
	hsai_BlockA1.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
	hsai_BlockA1.FrameInit.FSOffset = SAI_FS_FIRSTBIT;
	hsai_BlockA1.SlotInit.FirstBitOffset = 0;
	hsai_BlockA1.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
	hsai_BlockA1.SlotInit.SlotNumber = SAI_SLOTACTIVE_0;
	hsai_BlockA1.SlotInit.SlotActive = 0x00000003;
  if (HAL_SAI_Init(&hsai_BlockA1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SAI1_Init 2 */
 
  /* USER CODE END SAI1_Init 2 */
 
}
 
/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
 
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOE_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
 
}

Where MspInit is:

void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai)
{
 
  GPIO_InitTypeDef GPIO_InitStruct;
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
/* SAI1 */
    if(hsai->Instance==SAI1_Block_A)
    {
       /* Peripheral clock enable */
	   /** Initializes the peripherals clock */
		PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1;
		PeriphClkInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_CLKP;
		if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
		{
		  Error_Handler();
		}
 
		if (SAI1_client == 0)
		{
		   __HAL_RCC_SAI1_CLK_ENABLE();
		}
		SAI1_client ++;
 
		/**SAI1_A_Block_A GPIO Configuration
		PE2     ------> SAI1_CK1
		PD6     ------> SAI1_D1
		*/
		GPIO_InitStruct.Pin = GPIO_PIN_2;
		GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
		GPIO_InitStruct.Pull = GPIO_NOPULL;
		GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
		GPIO_InitStruct.Alternate = GPIO_AF2_SAI1;
		HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
 
		GPIO_InitStruct.Pin = GPIO_PIN_6;
		GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
		GPIO_InitStruct.Pull = GPIO_NOPULL;
		GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
		GPIO_InitStruct.Alternate = GPIO_AF2_SAI1;
		HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
 
	    __HAL_RCC_DMA2_CLK_ENABLE();	//>>__HAL_RCC_DMA1_CLK_ENABLE();
 
	    /* Configure the DMA handler for Reception process */
        gSai1_hdma_Rx.Instance                 = DMA2_Stream5;//>>DMA1_Stream0;//>>SPI4_RX_DMA_STREAM;
 
	    gSai1_hdma_Rx.Init.Request             = DMA_REQUEST_SAI1_A;
	    gSai1_hdma_Rx.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;//>>DMA_FIFOMODE_DISABLE;
	    gSai1_hdma_Rx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
	    gSai1_hdma_Rx.Init.MemBurst            = DMA_MBURST_SINGLE;//>>DMA_MBURST_INC4;
	    gSai1_hdma_Rx.Init.PeriphBurst         = DMA_MBURST_SINGLE;//>>DMA_MBURST_INC4;
	    gSai1_hdma_Rx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
	    gSai1_hdma_Rx.Init.PeriphInc           = DMA_PINC_DISABLE;
	    gSai1_hdma_Rx.Init.MemInc              = DMA_MINC_ENABLE;
	    gSai1_hdma_Rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;//>>DMA_PDATAALIGN_BYTE;
	    gSai1_hdma_Rx.Init.MemDataAlignment    = DMA_MDATAALIGN_HALFWORD;//>>DMA_MDATAALIGN_BYTE;
	    gSai1_hdma_Rx.Init.Mode                = DMA_CIRCULAR;//DMA_NORMAL;
	    gSai1_hdma_Rx.Init.Priority            = DMA_PRIORITY_HIGH;
 
	    if( HAL_DMA_Init(&gSai1_hdma_Rx) == HAL_OK )
	    {
		  /* Select Callbacks functions called after Transfer complete and Transfer error */
/*
			  if(HAL_DMA_RegisterCallback(&gSai1_hdma_Rx, HAL_DMA_XFER_CPLT_CB_ID, SAI1_DMATransferCompletCplt) != HAL_OK)
			  {
			  }
*/
/*
			  if(HAL_DMA_RegisterCallback(&gSai1_hdma_Rx, HAL_DMA_XFER_ERROR_CB_ID, DMA_TransferErrorCallback)  != HAL_OK)
			  {
				Error_Handler();
			  }
*/
		  /* Associate the initialized DMA handle to the the SPI handle */
		  __HAL_LINKDMA(hsai, hdmarx, gSai1_hdma_Rx);
 
		  /* SAI DMA IRQ Channel configuration */
		  HAL_NVIC_SetPriority(DMA2_Stream5_IRQn, AUDIO_IN_IRQ_PREPRIO, 0);	//>>HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, AUDIO_IN_IRQ_PREPRIO, 0);
		  HAL_NVIC_EnableIRQ(DMA2_Stream5_IRQn);	//>>HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
        }
 
    }
}

I get into this ISR, but doesn't read nothing:

/**
 *
 */
void DMA2_Stream5_IRQHandler(void) //void DMA1_Stream0_IRQHandler(void)
{
	HAL_DMA_IRQHandler(&hsai_BlockA1);
}

What's wrong? Where cai I find the information about what DMA uses the SAI1_A?

After that I would like to convert PDM to PCM and then save data into USB file to check if the audio stream is converted correctly.

Thanks in advance to all who can help me on this issue.

Regards,

DM

DMast.1
Associate II

Hello everybody,

I still have the problem....someone can help me?

DMast.1
Associate II

Hi...an update....Finally I get the DMA isr but there is still a problem. After first transfer CPU enter in DMA Transfer Error Interrupt management.

Here is the sample code:

#define AUDIO_FREQUENCY			AUDIO_FREQUENCY_96K	//AUDIO_FREQUENCY_44K
int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  if( MX_SAI1_ClockConfig(&hsai_BlockA1, AUDIO_FREQUENCY) != HAL_OK )
  {
 
  }
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SAI1_Init(AUDIO_FREQUENCY);
 
  /* USER CODE BEGIN 2 */
 
  /* Start the process receive DMA */
  HAL_SAI_Receive_DMA(&hsai_BlockA1, RxBuffer, sizeof(RxBuffer));
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
 
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
 
  /** Supply configuration update enable
  */
  HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
  /** Configure the main internal regulator output voltage
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
 
  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSIState = RCC_HSI_DIV1;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 400;
  RCC_OscInitStruct.PLL.PLLP = 2;
  RCC_OscInitStruct.PLL.PLLQ = 2;
  RCC_OscInitStruct.PLL.PLLR = 2;
  RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_1;
  RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
  RCC_OscInitStruct.PLL.PLLFRACN = 0;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
                              |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
  RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
 
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}
 
static void MX_SAI1_Init(uint32_t SampleRate)
{
 
  /* USER CODE BEGIN SAI1_Init 0 */
 
  /* USER CODE END SAI1_Init 0 */
 
  /* USER CODE BEGIN SAI1_Init 1 */
 
  /* USER CODE END SAI1_Init 1 */
 
	hsai_BlockA1.Instance = SAI1_Block_A;
	hsai_BlockA1.Init.Protocol = SAI_FREE_PROTOCOL;
	hsai_BlockA1.Init.AudioMode = SAI_MODEMASTER_RX;
	hsai_BlockA1.Init.DataSize = SAI_DATASIZE_8;
	hsai_BlockA1.Init.FirstBit = SAI_FIRSTBIT_MSB;
	hsai_BlockA1.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
	hsai_BlockA1.Init.Synchro = SAI_ASYNCHRONOUS;
	hsai_BlockA1.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
	hsai_BlockA1.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
	hsai_BlockA1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;
	hsai_BlockA1.Init.AudioFrequency = SampleRate;//>>SAI_AUDIO_FREQUENCY_44K;
	hsai_BlockA1.Init.MonoStereoMode = SAI_MONOMODE;
	hsai_BlockA1.Init.CompandingMode = SAI_NOCOMPANDING;
	hsai_BlockA1.Init.PdmInit.Activation = ENABLE;
	hsai_BlockA1.Init.PdmInit.MicPairsNbr = 1;
	hsai_BlockA1.Init.PdmInit.ClockEnable = SAI_PDM_CLOCK1_ENABLE;
	hsai_BlockA1.FrameInit.FrameLength = 16;
	hsai_BlockA1.FrameInit.ActiveFrameLength = 1;
	hsai_BlockA1.FrameInit.FSDefinition = SAI_FS_STARTFRAME;
	hsai_BlockA1.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
	hsai_BlockA1.FrameInit.FSOffset = SAI_FS_FIRSTBIT;
	hsai_BlockA1.SlotInit.FirstBitOffset = 0;
	hsai_BlockA1.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
	hsai_BlockA1.SlotInit.SlotNumber = SAI_SLOTACTIVE_0;
	hsai_BlockA1.SlotInit.SlotActive = 0x00000003;
  if (HAL_SAI_Init(&hsai_BlockA1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SAI1_Init 2 */
 
  /* USER CODE END SAI1_Init 2 */
 
}
 
#define AUDIO_IN_SAI_PDMx_DMAx_REQUEST        DMA_REQUEST_SAI1_A
 
/* SAI DMA Stream Rx definitions */
#define AUDIO_SAIx_DMAx_CLK_ENABLE()        __HAL_RCC_DMA1_CLK_ENABLE()
#define AUDIO_SAIx_DMAx_CLK_DISABLE()       __HAL_RCC_DMA1_CLK_DISABLE()
#define AUDIO_SAIx_DMAx_STREAM              DMA1_Stream2
#define AUDIO_SAIx_PDMx_DMAx_REQUEST        MDMA_REQUEST_DMA1_Stream2_TC   //>> #define AUDIO_SAIx_DMAx_CHANNEL             DMA1_CHANNEL_0
#define AUDIO_SAIx_DMAx_IRQ                 DMA1_Stream2_IRQn
#define AUDIO_SAIx_DMAx_PERIPH_DATA_SIZE    DMA_PDATAALIGN_HALFWORD
#define AUDIO_SAIx_DMAx_MEM_DATA_SIZE       DMA_MDATAALIGN_HALFWORD
#define AUDIO_SAIx_DMAx_IRQHandler          DMA1_Stream2_IRQHandler
 
/* Select the interrupt preemption priority and subpriority for the IT/DMA interrupt */
#define AUDIO_IN_IRQ_PREPRIO                ((uint32_t)7)   /* Select the preemption priority level(0 is the highest) */
 
void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai)
{
 
  GPIO_InitTypeDef GPIO_InitStruct;
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
    /* SAI1 */
    if(hsai->Instance==SAI1_Block_A)
    {
       /* Peripheral clock enable */
	   /** Initializes the peripherals clock */
		PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1;
		PeriphClkInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_CLKP;
		if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
		{
		  Error_Handler();
		}
 
		if (SAI1_client == 0)
		{
		   __HAL_RCC_SAI1_CLK_ENABLE();
		}
		SAI1_client ++;
 
		/**SAI1_A_Block_A GPIO Configuration
		PE2     ------> SAI1_CK1
		PD6     ------> SAI1_D1
		*/
		GPIO_InitStruct.Pin = GPIO_PIN_2;
		GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
		GPIO_InitStruct.Pull = GPIO_NOPULL;
		GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
		GPIO_InitStruct.Alternate = GPIO_AF2_SAI1;
		HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
 
		GPIO_InitStruct.Pin = GPIO_PIN_6;
		GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
		GPIO_InitStruct.Pull = GPIO_NOPULL;
		GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
		GPIO_InitStruct.Alternate = GPIO_AF2_SAI1;
		HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
 
 
	    /* Enable the DMA clock */
	    AUDIO_SAIx_DMAx_CLK_ENABLE();
 
	  /* Configure the hdma_sai_rx handle parameters */
	  gSai1_hdma_Rx.Init.Request             = AUDIO_IN_SAI_PDMx_DMAx_REQUEST; //gSai1_hdma_Rx.Init.Channel             = AUDIO_SAIx_DMAx_CHANNEL;
	  gSai1_hdma_Rx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
	  gSai1_hdma_Rx.Init.PeriphInc           = DMA_PINC_DISABLE;
	  gSai1_hdma_Rx.Init.MemInc              = DMA_MINC_ENABLE;
	  gSai1_hdma_Rx.Init.PeriphDataAlignment = AUDIO_SAIx_DMAx_PERIPH_DATA_SIZE;
	  gSai1_hdma_Rx.Init.MemDataAlignment    = AUDIO_SAIx_DMAx_MEM_DATA_SIZE;
	  gSai1_hdma_Rx.Init.Mode                = DMA_CIRCULAR;
	  gSai1_hdma_Rx.Init.Priority            = DMA_PRIORITY_HIGH;
	  gSai1_hdma_Rx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
	  gSai1_hdma_Rx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
	  gSai1_hdma_Rx.Init.MemBurst            = DMA_MBURST_SINGLE;
	  gSai1_hdma_Rx.Init.PeriphBurst         = DMA_MBURST_SINGLE;
 
	  gSai1_hdma_Rx.Instance = AUDIO_SAIx_DMAx_STREAM;
 
	  /* Associate the DMA handle */
	  __HAL_LINKDMA(hsai, hdmarx, gSai1_hdma_Rx);
 
	  /* Deinitialize the Stream for new transfer */
	  HAL_DMA_DeInit(&gSai1_hdma_Rx);
 
	  /* Configure the DMA Stream */
	  HAL_DMA_Init(&gSai1_hdma_Rx);
 
 
	   /* I2S DMA IRQ Channel configuration */
	   HAL_NVIC_SetPriority(AUDIO_SAIx_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0);
	   HAL_NVIC_EnableIRQ(AUDIO_SAIx_DMAx_IRQ);
    }
}

Any suggest about fix this issue. Thanks in advance.

DM

DMast.1
Associate II

Hi all, at this moment finally I get data from DMA (Half Transfert and FullTranfert ISR)....now how can I proceed to convert the audio stream to PCM and then save if in a file (on usb stick)? Is there an example that can I get inspire to achive this final result?

Thanks to all how can help me.

Regards,

DM