2026-04-22 4:44 AM - last edited on 2026-04-22 4:51 AM by Andrew Neil
Hi Community,
I am working on STM32H747I-DISCO Board and trying to bringup digital MEMS Mic (MP34DT05) which is integrated on STM32H7-DISCO Board.
I am trying to record random voice for 5 seconds and need to play back via audio jack out which is connected to codec also it is integrated on the board. I am sharing you schematic of the board as below:
MP34DT05 is connected to MCU directly with SAI4 Interface and Solder Brifdges are provided to connect via codec
Here I developed the application code to interface and record via MIC and playback via Audio Jack out.
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stm32h747i_discovery_audio.h"
#include <math.h>
#include"log.h"
#include<string.h>
#include "pdm_config.h"
#include "pdm2pcm_glo.h"
#include <stdio.h>
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define AUDIO_MIC_INIT
//#define AUDIO_JACK_INIT
//#define AUDIO_BUFFER_SIZE 2048
/************** AUDIO CONFIG *************************/
#define SAMPLE_RATE 16000
#define RECORD_TIME_SEC 4
#define PCM_CHUNK (SAMPLE_RATE / 1000) // 16
#define PDM_CHUNK (PCM_CHUNK * 64) // 1024
#define PCM_TOTAL_SAMPLES (SAMPLE_RATE * RECORD_TIME_SEC) //16000*4
#define PCM_BUFFER_SIZE (PCM_TOTAL_SAMPLES)
#define PDM_BUFFER_SIZE 1024
#define AUDIO_OUT_SAMPLES (PCM_TOTAL_SAMPLES * 2)
#define AUDIO_INSTANCE 0
/* DUAL_CORE_BOOT_SYNC_SEQUENCE: Define for dual core boot synchronization */
/* demonstration code based on hardware semaphore */
/* This define is present in both CM7/CM4 projects */
/* To comment when developping/debugging on a single core */
//#define DUAL_CORE_BOOT_SYNC_SEQUENCE
#if defined(DUAL_CORE_BOOT_SYNC_SEQUENCE)
#ifndef HSEM_ID_0
#define HSEM_ID_0 (0U) /* HW semaphore 0*/
#endif
#endif /* DUAL_CORE_BOOT_SYNC_SEQUENCE */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c4;
SAI_HandleTypeDef hsai_BlockA1;
SAI_HandleTypeDef hsai_BlockB1;
SAI_HandleTypeDef hsai_BlockA4;
UART_HandleTypeDef huart1;
SDRAM_HandleTypeDef hsdram1;
/* USER CODE BEGIN PV */
/* ================= SDRAM BUFFER ================= */
__attribute__((section(".sdram")))
uint16_t pcm_sdram_buffer[PCM_TOTAL_SAMPLES];
uint16_t audio_out_buffer[AUDIO_OUT_SAMPLES];
/****************Buffers *******************/
uint16_t pdm_buffer[PDM_CHUNK];
uint16_t pcm_chunk[PCM_CHUNK];
int16_t stereo_buffer[PCM_BUFFER_SIZE * 2];
//int16_t audio_buffer[AUDIO_BUFFER_SIZE];
PDM_Filter_Handler_t PDM_FilterHandler; // Handler (internal memory)
PDM_Filter_Config_t PDM_FilterConfig; // Configuration
/* Global variables */
volatile uint32_t pcm_index = 0;
volatile uint8_t recording_done = 0;
BSP_AUDIO_Init_t MicInit;
BSP_AUDIO_Init_t AudioOutInit;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void PeriphCommonClock_Config(void);
static void MPU_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C4_Init(void);
static void MX_SAI1_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_SAI4_Init(void);
static void MX_FMC_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
int32_t BSP_AUDIO_IN_PDMToPCM_Init(uint32_t Instance, uint32_t AudioFreq, uint32_t ChnlNbrIn, uint32_t ChnlNbrOut)
{
PDM_FilterHandler.bit_order = PDM_FILTER_BIT_ORDER_LSB;
PDM_FilterHandler.endianness = PDM_FILTER_ENDIANNESS_LE;
PDM_FilterHandler.high_pass_tap = 2104533974;
PDM_FilterHandler.out_ptr_channels = ChnlNbrOut;
PDM_FilterHandler.in_ptr_channels = ChnlNbrIn;
if(PDM_Filter_Init(&PDM_FilterHandler) != 0)
Error_Handler();
PDM_FilterConfig.decimation_factor = PDM_FILTER_DEC_FACTOR_64;
PDM_FilterConfig.output_samples_number = PCM_CHUNK; // 16
PDM_FilterConfig.mic_gain = 24;
if(PDM_Filter_setConfig(&PDM_FilterHandler, &PDM_FilterConfig) != 0)
Error_Handler();
return 0;
}
void PDM_To_PCM(uint16_t *pdm, uint16_t *pcm)
{
PDM_Filter((uint8_t*)pdm, pcm, &PDM_FilterHandler);
}
void Convert_Mono_To_Stereo(void)
{
for(uint32_t i = 0, j = 0; i < PCM_TOTAL_SAMPLES; i++, j += 2)
{
audio_out_buffer[j] = pcm_sdram_buffer[i]; // Left
audio_out_buffer[j + 1] = pcm_sdram_buffer[i]; // Right
}
}
//void GenerateSineWave(void)
//{
// for(int i = 0; i < AUDIO_BUFFER_SIZE; i++)
// {
// audio_buffer[i] = (uint16_t)(20000 * sin(2 * 3.14159 * i / 100));
// }
//}
#if defined(AUDIO_MIC_INIT)
void BSP_AUDIO_IN_HalfTransfer_CallBack(uint32_t Instance)
{
if(recording_done) return;
PDM_To_PCM(&pdm_buffer[0], pcm_chunk);
for(int i = 0; i < PCM_CHUNK/2; i++) // 8 samples
{
if(pcm_index < PCM_TOTAL_SAMPLES)
pcm_sdram_buffer[pcm_index++] = pcm_chunk[i];
else
{
recording_done = 1;
BSP_AUDIO_IN_Stop(1);
break;
}
}
}
void BSP_AUDIO_IN_TransferComplete_CallBack(uint32_t Instance)
{
if(recording_done) return;
PDM_To_PCM(&pdm_buffer[PDM_CHUNK/2], pcm_chunk);
for(int i = 0; i < PCM_CHUNK/2; i++) // 8 samples
{
if(pcm_index < PCM_TOTAL_SAMPLES)
pcm_sdram_buffer[pcm_index++] = pcm_chunk[i];
else
{
recording_done = 1;
BSP_AUDIO_IN_Stop(1);
break;
}
}
}
#endif
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* USER CODE BEGIN Boot_Mode_Sequence_0 */
#if defined(DUAL_CORE_BOOT_SYNC_SEQUENCE)
int32_t timeout;
#endif /* DUAL_CORE_BOOT_SYNC_SEQUENCE */
/* USER CODE END Boot_Mode_Sequence_0 */
/* MPU Configuration--------------------------------------------------------*/
MPU_Config();
/* USER CODE BEGIN Boot_Mode_Sequence_1 */
#if defined(DUAL_CORE_BOOT_SYNC_SEQUENCE)
/* Wait until CPU2 boots and enters in stop mode or timeout*/
timeout = 0xFFFF;
while((__HAL_RCC_GET_FLAG(RCC_FLAG_D2CKRDY) != RESET) && (timeout-- > 0));
if ( timeout < 0 )
{
Error_Handler();
}
#endif /* DUAL_CORE_BOOT_SYNC_SEQUENCE */
/* USER CODE END Boot_Mode_Sequence_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 Boot_Mode_Sequence_2 */
#if defined(DUAL_CORE_BOOT_SYNC_SEQUENCE)
/* When system initialization is finished, Cortex-M7 will release Cortex-M4 by means of
HSEM notification */
/*HW semaphore Clock enable*/
__HAL_RCC_HSEM_CLK_ENABLE();
/*Take HSEM */
HAL_HSEM_FastTake(HSEM_ID_0);
/*Release HSEM in order to notify the CPU2(CM4)*/
HAL_HSEM_Release(HSEM_ID_0,0);
/* wait until CPU2 wakes up from stop mode */
timeout = 0xFFFF;
while((__HAL_RCC_GET_FLAG(RCC_FLAG_D2CKRDY) == RESET) && (timeout-- > 0));
if ( timeout < 0 )
{
Error_Handler();
}
#endif /* DUAL_CORE_BOOT_SYNC_SEQUENCE */
/* USER CODE END Boot_Mode_Sequence_2 */
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C4_Init();
MX_SAI1_Init();
MX_USART1_UART_Init();
MX_SAI4_Init();
MX_FMC_Init();
/* USER CODE BEGIN 2 */
#if defined(AUDIO_MIC_INIT)
/* === AUDIO IN (digital mic - Instance 1) === */
MicInit.Device = AUDIO_IN_DEVICE_DIGITAL_MIC;
MicInit.SampleRate = AUDIO_FREQUENCY_16K;
MicInit.BitsPerSample = AUDIO_RESOLUTION_16B;
MicInit.ChannelsNbr = 1;
MicInit.Volume = 100;
if (BSP_AUDIO_IN_Init(0, &MicInit) != BSP_ERROR_NONE) {
Error_Handler();
}else{
LOG("Audio In Successfully Configured....\r\n");
}
/* PDM → PCM conversion setup (1 mic in → stereo PCM out for easy playback) */
BSP_AUDIO_IN_PDMToPCM_Init(AUDIO_INSTANCE, AUDIO_FREQUENCY_16K, 1, 1);
/* -------- START RECORDING -------- */
BSP_AUDIO_IN_RecordPDM(0, (uint8_t*)pdm_buffer, PDM_BUFFER_SIZE);
printf("Recording started...\r\n");
while(!recording_done);
/* -------- MONO → STEREO -------- */
Convert_Mono_To_Stereo();
printf("Recording DONE: %lu samples\r\n", pcm_index);
#endif
#if defined(AUDIO_JACK_INIT)
AudioOutInit.Device=AUDIO_OUT_DEVICE_HEADPHONE;//Output device Headphone
AudioOutInit.SampleRate=AUDIO_FREQUENCY_48K;//48Khz
AudioOutInit.BitsPerSample=AUDIO_RESOLUTION_16B;//16bit resolution
AudioOutInit.ChannelsNbr=2;//1 for MONO and 2 for Stereo
AudioOutInit.Volume=50;
if(BSP_AUDIO_OUT_Init(AUDIO_INSTANCE, &AudioOutInit)!= BSP_ERROR_NONE){
LOG("BSP_AUDIO_OUT is fail to initialize");
}else{
LOG("BSP_AUDIO_OUT is initialize...\r\n");
}
LOG("Playing Audio...\r\n");
BSP_AUDIO_OUT_Play(0,(uint8_t*)audio_out_buffer,AUDIO_OUT_SAMPLES * 2);
// GenerateSineWave();
#endif
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
When I run this code i am facing issue at BSP_AUDIO_IN_PDMToPCM_Init();
Code is stuck at that function and not moving forward.
I need your suggestion/modifications of the code to work properly and what changes i need to do for BSP_AUDIO_IN_PDMToPCM_Init() function to work correctly
Note : I added required driver files(discovery files) for codec config and mic config.
Added : pdm2pcm_glo.h file ,
lib: libPDMFilter_CM7_GCC_wc32.a
I am sharing you reference project. for better understanding
Working On:
CubeIDE: Version 1.19.0
FW Package: STM32H7 1.12.1
If issue is solved, share the updated file.
Clear me below questions:
1.MIC is shared by SAI4(MCU) and SAI1(codec). So to get PDM data which Interface I need to prefer?
2.How to do this PDM to PCM convertion?
Edited to apply source code formatting - please see How to insert source code for future reference.
2026-04-22 5:12 AM
Hello,
@rabbani_sk wrote:
When I run this code i am facing issue at BSP_AUDIO_IN_PDMToPCM_Init();
Code is stuck at that function and not moving forward.
You need to debug that and find where it stucks. Maybe your application falls into Error_Handler() / while(1) or you go into a Hard fault!
2026-04-27 10:33 PM
Can you provide any reference example to read the PDM data via this MIC using appropriate interface.
Since I am trying to get data via SAI4 interface but unable to get it.
And one more issue is when I enable DMA and global Interrupt the callbacks are failing during debugging.
Provide me any example code to interface on this board and what ioc configuration is required for reading the PDM data.
2026-04-28 1:42 AM
@rabbani_sk wrote:
Can you provide any reference example to read the PDM data via this MIC using appropriate interface.
Since I am trying to get data via SAI4 interface but unable to get it.
The only example I can suggest is the one provided in CubeH7: https://github.com/STMicroelectronics/STM32CubeH7/blob/master/Projects/STM32H743I-EVAL/Examples/DFSDM/DFSDM_AudioRecord
Hope that helps