2025-08-06 11:22 AM
Hello,
I am trying to get I2S and DMA working on my stm32wb55 microcontroller. I want to read data from an INMP441 (or similar). I did try to use the STCube IDE (or MX) to configure I2S and DMA using tutorials from the internet but this also did not work. The tutorials are all made for other ST-microcontrollers though.
I either have a problem setting up the DMA, SAI (for I2S) or the DMA interrupt. I do not really have any idea where my problem lies. Just using the standard configurations from STCube do not seem to work.
Does anyone here have any experience with the STM32WB55 and the SAI of this Microcontroller in particular? I am using the WeAct STM32WB55CGU6 for testing.
Thanks a lot for helping me out here.
Solved! Go to Solution.
2025-08-07 2:23 PM
Okay, so it's doing, what you set it to do: nothing.
First, set clock tree to something useful...
SAI clock 48M, maybe ok, but core to max, I don't know now, maybe also 48M.
Now it's at 4.... this cannot do anything useful.
Then start it, maybe HAL_SAI_DMA_START(), or so. To the data array you want the data to get then.
2025-08-06 12:25 PM
Hi,
The SAI is working fine, just set it to the mode you need. Master receive, 16bit, two slots, ... maybe.
Then set a DMA Channel for circular mode, with 16b , half word, source and destination.
Enable callback in Cube project settings for the SAI, generate code.
In program then set an array int16_t , big enough, let's say 16KB .
Then start the SAI in DMA mode, once, that's it.
Now in callback half and full, you get the data, to copy and use it. That's it.
2025-08-07 1:47 PM
HI AScha.3,
I am not quite sure if I can recreate what you suggested.
So starting from the bare minimum, here are the settings I tried in the STMCube configurator to get the INMP441 to work on the STM32WB55:
And the generated code (without any own code or comments) was this:
#include "main.h"
SAI_HandleTypeDef hsai_BlockA1;
DMA_HandleTypeDef hdma_sai1_a;
void SystemClock_Config(void);
void PeriphCommonClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_SAI1_Init(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
PeriphCommonClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_SAI1_Init();
while (1)
{
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
__HAL_RCC_PLL_PLLM_CONFIG(RCC_PLLM_DIV1);
__HAL_RCC_PLL_PLLSOURCE_CONFIG(RCC_PLLSOURCE_MSI);
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK4|RCC_CLOCKTYPE_HCLK2
|RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.AHBCLK2Divider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLK4Divider = RCC_SYSCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
void PeriphCommonClock_Config(void)
{
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SMPS;
PeriphClkInitStruct.SmpsClockSelection = RCC_SMPSCLKSOURCE_HSI;
PeriphClkInitStruct.SmpsDivSelection = RCC_SMPSCLKDIV_RANGE1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
}
static void MX_SAI1_Init(void)
{
hsai_BlockA1.Instance = SAI1_Block_A;
hsai_BlockA1.Init.AudioMode = SAI_MODEMASTER_RX;
hsai_BlockA1.Init.Synchro = SAI_ASYNCHRONOUS;
hsai_BlockA1.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
hsai_BlockA1.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
hsai_BlockA1.Init.MckOverSampling = SAI_MCK_OVERSAMPLING_DISABLE;
hsai_BlockA1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;
hsai_BlockA1.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_16K;
hsai_BlockA1.Init.SynchroExt = SAI_SYNCEXT_DISABLE;
hsai_BlockA1.Init.MonoStereoMode = SAI_MONOMODE;
hsai_BlockA1.Init.CompandingMode = SAI_NOCOMPANDING;
if (HAL_SAI_InitProtocol(&hsai_BlockA1, SAI_I2S_STANDARD, SAI_PROTOCOL_DATASIZE_24BIT, 2) != HAL_OK)
{
Error_Handler();
}
}
static void MX_DMA_Init(void)
{
__HAL_RCC_DMAMUX1_CLK_ENABLE();
__HAL_RCC_DMA1_CLK_ENABLE();
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
HAL_NVIC_SetPriority(DMAMUX1_OVR_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMAMUX1_OVR_IRQn);
}
static void MX_GPIO_Init(void)
{
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
}
void Error_Handler(void)
{
__disable_irq();
while (1)
{
}
}
2025-08-07 2:23 PM
Okay, so it's doing, what you set it to do: nothing.
First, set clock tree to something useful...
SAI clock 48M, maybe ok, but core to max, I don't know now, maybe also 48M.
Now it's at 4.... this cannot do anything useful.
Then start it, maybe HAL_SAI_DMA_START(), or so. To the data array you want the data to get then.
2025-08-07 10:39 PM
I overlooked the issue with the max clock, thanks I will try that.
I did let Cube auto set the clocks. Weird, for this simple setup I would trust Cube to be able to set usefull clocks....
2025-08-10 11:38 PM - edited 2025-08-10 11:38 PM
The Core Clock was the issue. I got it working now with 64 MHz. Thanks for spotting it.