2020-08-26 07:01 AM - last edited on 2023-10-13 08:40 AM by Amel NASRI
Hi all,
I try implement measuring sound level (SPL). I choose mic MP34DT05-A with PDM and connect to nucleo STM32WB55RG:
- data of mic connected to SAI_D1_PC3
- clock od mic connected to SAI1_CK1_PB8
- used the one mic so input of mic LR connected to GND (or VCC)
To generate code (setting of register) I used described example from section 4.3 of datasheet "Examples of configuration based on STM32CubeMX AN5027" and CubeMX.
and DMA:
Then I got two functions for the comprehensive PDM configuration:
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_16;
hsai_BlockA1.Init.FirstBit = SAI_FIRSTBIT_LSB;
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_DISABLE;
hsai_BlockA1.Init.MckOverSampling = SAI_MCK_OVERSAMPLING_DISABLE;
hsai_BlockA1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;
hsai_BlockA1.Init.MonoStereoMode = SAI_STEREOMODE;
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_HIGH;
hsai_BlockA1.FrameInit.FSOffset = SAI_FS_FIRSTBIT;
hsai_BlockA1.SlotInit.FirstBitOffset = 0;
hsai_BlockA1.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
hsai_BlockA1.SlotInit.SlotNumber = 1;
hsai_BlockA1.SlotInit.SlotActive = 0x0000FFFF;
if (HAL_SAI_Init(&hsai_BlockA1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SAI1_Init 2 */
tr_info("read status");
tr_info("status sai '1' ready: %d", HAL_SAI_GetState(&hsai_BlockA1));
/* USER CODE END SAI1_Init 2 */
}
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMAMUX1_CLK_ENABLE();
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Channel1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}
So I put these funtions to simple mbed example code:
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*/
#include "mbed.h"
#include "ThisThread.h"
#include "mbed-trace/mbed_trace.h"
#define TRACE_GROUP "MAIN"
DigitalOut led1(LED1);
SAI_HandleTypeDef hsai_BlockA1;
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
tr_info("error");
/* USER CODE END Error_Handler_Debug */
}
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_16;
hsai_BlockA1.Init.FirstBit = SAI_FIRSTBIT_LSB;
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_DISABLE;
hsai_BlockA1.Init.MckOverSampling = SAI_MCK_OVERSAMPLING_DISABLE;
hsai_BlockA1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;
hsai_BlockA1.Init.MonoStereoMode = SAI_STEREOMODE;
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_HIGH;
hsai_BlockA1.FrameInit.FSOffset = SAI_FS_FIRSTBIT;
hsai_BlockA1.SlotInit.FirstBitOffset = 0;
hsai_BlockA1.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
hsai_BlockA1.SlotInit.SlotNumber = 1;
hsai_BlockA1.SlotInit.SlotActive = 0x0000FFFF;
if (HAL_SAI_Init(&hsai_BlockA1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SAI1_Init 2 */
tr_info("read status");
tr_info("status sai (if'1' => sai ready to use): %d", HAL_SAI_GetState(&hsai_BlockA1));
/* USER CODE END SAI1_Init 2 */
}
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMAMUX1_CLK_ENABLE();
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Channel1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}
int main()
{
mbed_trace_init();
mbed_trace_config_set(TRACE_ACTIVE_LEVEL_INFO);
tr_info("START");
MX_SAI1_Init();
MX_DMA_Init();
ThisThread::sleep_for(1000);
uint16_t sound_len = 10;
uint8_t sound_in[sound_len];
while (true) {
led1 = !led1;
ThisThread::sleep_for(5000);
uint8_t hal_status = HAL_SAI_Receive(&hsai_BlockA1, sound_in, 10, 1000);
if (hal_status != HAL_OK)
{
tr_info("hal status (if '0' => OK): %d", hal_status);
tr_info("status sai (if'1' => sai ready to use): %d,", HAL_SAI_GetState(&hsai_BlockA1));
Error_Handler();
}
else
{
tr_info("hal status OK");
tr_info("data: %s", mbed_trace_array(hsai_BlockA1.pBuffPtr, 10));
tr_info("sound in %s", mbed_trace_array(sound_in, sound_len));
}
}
}
To read mic data I used function:
HAL_SAI_Receive(&hsai_BlockA1, sound_in, 10, 1000);
but it recive error status HAL_ERROR
In mbed I don't change the clock setting so that may generate the error - I need connect clock to SAI periferia. Mbed doesn't give API to re-configure that - I don't want to do it on my own.
Or I made a configuration error.
someone can help me? I just need only read sound level not record or stream it anywhere.