2019-07-19 02:40 AM
Hello,
I am trying to develop a noise canceling microphone using the STM32F401RET6 based on the software Acoustic_BF provided by the package X-CUBE-MEMSMIC1 :
https://www.st.com/en/embedded-software/x-cube-memsmic1.html
In this software the audio is sent to the PC by USB and instead of sending through USB I want to send it via the I2S3 BUS.
I encounter two problems :
1) When I try to enable the DMA of the i2s3 channel the BEAMFORMING stop working. When I visualize the audio data using audacity, only the audio channel not processed by the beamforming remain. The audio who supposed to be beamformed have some glitch (two glitch in the picture below) but the signal remain at 0 for the rest of the time.
The input I2S2 (DMA_CHANNEL_3, DMA2_Stream2) doesn't seem to use some common DMA with the output (DMA1_Stream5, DMA_CHANNEL_0) so the beamforming shouldn't been affected by the DMA output of the I2S3. Is there incompatiblity for performing the beamforming and sending it to the I2S3 at the same time ?
2) The second problem encountered is for the configuration of the I2S3 clock frequency.
I have generated the structure of SystemClock_Config using STM32CUBEMX for having a I2S3 output frequency of 16.0KHz. Considering the datasheet and STM32CUBEMX the configuration for the PLLI2S should be :
PLLI2SN = 213;
PLLI2SR = 2;
With this value I obtain 15.8KHZ instead of the 16.0KHZ rendering the synchronization between the input and the output more difficult.
By modifying the value of PLLI2S the output frequency doesn't change. I don't understand why the frequency doesn't change in my prototype because according to STM32CUBEMX the frequency depend on the configuration of PLLI2SN and PLLI2SR ....
The second problem seem close to the issue encounter here with the I2S3 output too slow :
But the first issue is really block me....
I join the STM32CUBEMX files and my project files and i hope somebody can help me.
here is the configuration of my clock and I2S3 :
void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
/* Enable Power Control clock */
__PWR_CLK_ENABLE();
/* The voltage scaling allows optimizing the power consumption when the device is
clocked below the maximum system frequency, to update the voltage scaling value
regarding system frequency refer to product datasheet. */
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
//HSE for AUDIO_IN HSI
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;//RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;//RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 16;//8;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
RCC_OscInitStruct.PLL.PLLQ = 7;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;
PeriphClkInitStruct.PLLI2S.PLLI2SN = 213;
PeriphClkInitStruct.PLLI2S.PLLI2SR = 2;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10, SET);//NO ERROR => init is ok
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14, SET);//NO ERROR => init is ok
// Error_Handler();
}
}
static void MX_I2S3_Init(void)
{
int ret=0;
/* USER CODE BEGIN I2S3_Init 0 */
/* USER CODE END I2S3_Init 0 */
/* USER CODE BEGIN I2S3_Init 1 */
static DMA_HandleTypeDef hdma_i2sTx;
/* USER CODE END I2S3_Init 1 */
hi2s3.Instance = SPI3;
hi2s3.Init.Mode = I2S_MODE_MASTER_TX;
hi2s3.Init.Standard = I2S_STANDARD_MSB;//I2S_STANDARD_PHILLIPS;//I2S_STANDARD_MSB
hi2s3.Init.DataFormat = I2S_DATAFORMAT_24B;
hi2s3.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE;
hi2s3.Init.AudioFreq = I2S_AUDIOFREQ_16K;//I2S_AUDIOFREQ_16K;
hi2s3.Init.CPOL = I2S_CPOL_LOW;
hi2s3.Init.ClockSource = I2S_CLOCK_PLL;
hi2s3.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_DISABLE;
if (HAL_I2S_Init(&hi2s3) != HAL_OK)
{
// Error_Handler();
}
/* Enable the DMA clock */
AUDIO_OUT_I2S_DMAx_CLK_ENABLE();
/* Configure the hdma_i2sRx handle parameters */
hdma_i2sTx.Init.Channel = AUDIO_OUT_I2S_DMAx_CHANNEL;
hdma_i2sTx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_i2sTx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_i2sTx.Init.MemInc = DMA_MINC_DISABLE;//DMA_MINC_ENABLE;
hdma_i2sTx.Init.PeriphDataAlignment = AUDIO_OUT_I2S_DMAx_PERIPH_DATA_SIZE;
hdma_i2sTx.Init.MemDataAlignment = AUDIO_OUT_I2S_DMAx_MEM_DATA_SIZE;
hdma_i2sTx.Init.Mode = DMA_CIRCULAR;//DMA_NORMAL;//DMA_CIRCULAR;
hdma_i2sTx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_i2sTx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;//DMA_FIFOMODE_DISABLE;
hdma_i2sTx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_i2sTx.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_i2sTx.Init.PeriphBurst = DMA_MBURST_SINGLE;
hdma_i2sTx.Instance = AUDIO_OUT_I2S_DMAx_STREAM;
/* Associate the DMA handle */
__HAL_LINKDMA(&hi2s3, hdmatx, hdma_i2sTx);
/* Deinitialize the Stream for new transfer */
if (HAL_DMA_DeInit(&hdma_i2sTx) != HAL_OK)
{
ret = HAL_ERROR;
}
/* Configure the DMA Stream */
if (HAL_DMA_Init(&hdma_i2sTx) != HAL_OK)
{
ret = HAL_ERROR;
}
/* I2S DMA IRQ Channel configuration */
HAL_NVIC_SetPriority(AUDIO_OUT_I2S_DMAx_IRQ, CCA02M1_AUDIO_OUT_IT_PRIORITY, 0);
HAL_NVIC_EnableIRQ( AUDIO_OUT_I2S_DMAx_IRQ);
ret = HAL_I2S_Transmit_DMA(&hi2s3,(uint16_t *) AUDIO_OUT_BUFFER_DMA, I2S_BUFFER_SIZE);
/* USER CODE BEGIN I2S3_Init 2 */
/* USER CODE END I2S3_Init 2 */
}
Best regards