Problem with enabling onboard MEMS microphone using SAI interface on STM32H735IG discovery board
/* SAI configured in Mode: Pulse Width Modulation using MicroPhones pairs (1-2) and CK2 as clock */
static void MX_SAI4_Init(void)
{
hsai_BlockA4.Instance = SAI4_Block_A;
hsai_BlockA4.Init.Protocol = SAI_FREE_PROTOCOL;
hsai_BlockA4.Init.AudioMode = SAI_MODEMASTER_RX;
hsai_BlockA4.Init.DataSize = SAI_DATASIZE_8;
hsai_BlockA4.Init.FirstBit = SAI_FIRSTBIT_MSB;
hsai_BlockA4.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
hsai_BlockA4.Init.Synchro = SAI_ASYNCHRONOUS;
hsai_BlockA4.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
hsai_BlockA4.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
hsai_BlockA4.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;
hsai_BlockA4.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_16K;
hsai_BlockA4.Init.MonoStereoMode = SAI_STEREOMODE;
hsai_BlockA4.Init.CompandingMode = SAI_NOCOMPANDING;
hsai_BlockA4.Init.PdmInit.Activation = ENABLE;
hsai_BlockA4.Init.PdmInit.MicPairsNbr = 1;
hsai_BlockA4.Init.PdmInit.ClockEnable = SAI_PDM_CLOCK2_ENABLE;
hsai_BlockA4.FrameInit.FrameLength = 8;
hsai_BlockA4.FrameInit.ActiveFrameLength = 1;
hsai_BlockA4.FrameInit.FSDefinition = SAI_FS_STARTFRAME;
hsai_BlockA4.FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
hsai_BlockA4.FrameInit.FSOffset = SAI_FS_FIRSTBIT;
hsai_BlockA4.SlotInit.FirstBitOffset = 0;
hsai_BlockA4.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
hsai_BlockA4.SlotInit.SlotNumber = 1;
hsai_BlockA4.SlotInit.SlotActive = 0x00000001;
if (HAL_SAI_Init(&hsai_BlockA4) != HAL_OK)
{
Error_Handler();
}
}void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
/* SAI4 */
if(hsai->Instance==SAI4_Block_A)
{
/* Peripheral clock enable */
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI4A;
PeriphClkInitStruct.PLL2.PLL2M = 4;
PeriphClkInitStruct.PLL2.PLL2N = 12;
PeriphClkInitStruct.PLL2.PLL2P = 3;
PeriphClkInitStruct.PLL2.PLL2Q = 2;
PeriphClkInitStruct.PLL2.PLL2R = 2;
PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_3;
PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
PeriphClkInitStruct.PLL2.PLL2FRACN = 0.0;
PeriphClkInitStruct.Sai4AClockSelection = RCC_SAI4ACLKSOURCE_PLL2;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
if (SAI4_client == 0)
{
__HAL_RCC_SAI4_CLK_ENABLE();
/* Peripheral interrupt init*/
HAL_NVIC_SetPriority(SAI4_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SAI4_IRQn);
}
SAI4_client ++;
/**SAI4_A_Block_A GPIO Configuration
PE5 ------> SAI4_CK2
PD6 ------> SAI4_D1
*/
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF10_SAI4;
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_AF1_SAI4;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
}
}With that configuration I am receiving interrupts that are handled in ISR:
void SAI4_IRQHandler(void)
{
HAL_SAI_IRQHandler(&hsai_BlockA4);
}That I am confirming in main loop:
#define BUFF_SIZE 4092
uint8_t buffer[BUFF_SIZE];
volatile int i = 0;
volatile int it_error = 0; // not used in this example
volatile int it_read = 0;
volatile int old_it_read = 0;
void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai_BlockA4)
{
it_read++;
}
void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai_BlockA4)
{
it_error = 1;
}
SAI_HandleTypeDef hsai_BlockA4;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SAI4_Init(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SAI4_Init();
HAL_StatusTypeDef ret;
ret = HAL_SAI_Receive_IT(&hsai_BlockA4, (uint8_t *)buffer, (uint16_t)BUFF_SIZE);
while (1)
{
i++;
/* check if `it_read` changed - if yes, buffer is complete */
if (old_it_read != it_read)
{
old_it_read = it_read;
/* start again */
HAL_SAI_Receive_IT(&hsai_BlockA4, (uint8_t *)buffer, (uint16_t)BUFF_SIZE);
}
}
}But every buffer is filled with "255" values.
I was assuming that I will receive buffer of PDM values. Can you show me where I can find solution for my problem or how I can solve it?
I tried to follow multiple examples (from BSP, SAI and others) as well tried to use Interfacing PDM microphones application note (AN5027) but with no success.
Any help would be appreciated,
Pawel
