AnsweredAssumed Answered

Understanding I2S and SAI clock configuration

Question asked by Matti Sillanpää on Mar 13, 2017
Latest reply on May 17, 2017 by Matti Sillanpää

Hi.

 

 

So I've got STM32F469I-Discovery board. I've connected MEMS microphone to I2S input that outputs 16khz and 16bit (in 32bit frame) stereo PCM output. I'm using the SAI1 via BSP_AUDIO interface (defined in stm32469i_discovery_audio.c) to output data to audio codec like in audio record and playback example. Only difference is the data rate of the source.

 

Anyho I'm totally baffled with the clock configuration. I've read the reference manual SAI part and what ever I've managed to google about the STM SAI/I2S clock generation. Also I've tried to setup them via CubeMX. However none of the configurations seem to work properly, but I managed to iterate the clock in ballpark just by changing the PLLSAI.PLLSAIN by hand. However I really don't understand how should I really calculate the clocks properly. Is there any documentation that would clear this?

 

Input I2S: 16bit stereo in 32bit frame @ 16khz (1.029Mhz clock checked with scope)

 

About working config:

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 16;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 15;
RCC_OscInitStruct.PLL.PLLN = 144;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 5;
RCC_OscInitStruct.PLL.PLLR = 2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}

/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}

PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S|RCC_PERIPHCLK_SAI_PLLSAI
|RCC_PERIPHCLK_SDIO|RCC_PERIPHCLK_CLK48;
PeriphClkInitStruct.PLLI2S.PLLI2SN = 192;
PeriphClkInitStruct.PLLI2S.PLLI2SR = 2;
// PeriphClkInitStruct.PLLSAI.PLLSAIN = 116;
// PeriphClkInitStruct.PLLSAI.PLLSAIN = 213;
PeriphClkInitStruct.PLLSAI.PLLSAIN = 240;
PeriphClkInitStruct.PLLSAI.PLLSAIQ = 2;
PeriphClkInitStruct.PLLSAIDivQ = 1;
PeriphClkInitStruct.Clk48ClockSelection = RCC_CLK48CLKSOURCE_PLLQ;
PeriphClkInitStruct.SdioClockSelection = RCC_SDIOCLKSOURCE_CLK48;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{

The 240 SAIn isn't even close to one suggested by cubemx. Can anyone open this up at all?

Outcomes