Skip to main content
Senior II
December 21, 2025
Question

Trying to source a 12.288MHz clock for STM32L433

  • December 21, 2025
  • 7 replies
  • 2531 views

 

I am trying to source a 12.288MHz clock for an STM32L433 but having difficulties finding something.

The clock is required for I2S playback with a bluetooth receiver (BT401).

I have tried using the internal MSI RC to generate the 12.288MHz clock for SAI,  but the BT401 is misbehaving so it might be because the MSI RC clock has too much jitter.

I was wondering if a ASFL1-12.288MHZ-EC-T would be suitable for the clock source for the SAI external clock input....

https://uk.rs-online.com/web/p/crystal-oscillators/2403583

Below is the setup... 

 

freeflyer_0-1766340884039.png

 

The I2S amplifier (MAX98357A) seems to work fine with the 12.288MHz clock generated by the internal MSI RC and PLL.

 

But the BT401 either requires multiple attempts to start playing and sometimes plays just a screeching sound for a few seconds then stops.  So I need to rule out whether the issue is caused by clock jitter by trying a more accurate clock source.

 

I am currently using the STM32L433 Nucleo board which has a footprint for an external HSE crystal, but I cannot find a crystal for that footpring with a 12.288MHz frequency.

 

The ASFL1-12.288MHZ-EC-T seems to be an all in one device, you just provide power and it generates the output clock.  So its not like a crystal which needs a special drive circuit ?

 

I have read the application note AN2867 Recommended resonators for STM32 MCUs/MPUs, but its complicated and just confused me.

7 replies

December 21, 2025

Yes, the ASFL1-12.288MHz-EC-T would be suitable for your setup. Unlike a passive crystal that requires a carefully designed oscillator circuit, the ASFL1 is a complete clock module — you simply provide power and it outputs a stable 12.288 MHz clock. This avoids problems like MSI RC clock jitter, which you’ve already noticed is affecting the BT401 Bluetooth module.

A few points to consider:

  1. Output compatibility: Check that the voltage levels of the ASFL1 match the STM32L433 SAI/SAI_EXTCLK input. Typically, it outputs CMOS levels, which are compatible.

  2. Decoupling: Place a good decoupling capacitor near the module’s power pin to reduce noise.

  3. Routing: Keep the clock trace short and avoid routing near high-speed signals to minimize jitter pickup.

Using an external oscillator like the ASFL1 is a common solution for audio applications, especially when precise clocks are required for I2S or SAI. In fact, while experimenting with Eden Emulator Download  hardware prototypes, we faced similar issues with BT modules misbehaving due to internal RC clock jitter, and switching to a dedicated 12.288 MHz oscillator solved the problem completely. My website link is https://edenemu.com

So for your STM32L433 + BT401 setup, the ASFL1 should provide a clean, low-jitter clock and eliminate the audio glitches you’re seeing.

freeflyerAuthor
Senior II
December 21, 2025

Many thanks morries, its reassuring to hear that the ASFL1 is suitable and that you also had similar issues which were fixed by using a more accurate clock.  I checked the ASFL1 voltage and it is 3.3V.

On the Nucleo developmnet board I will have to 'dead-bug' wire the ASFL1 and capcacitor to test it, but I will be designing my own PCB once I have found a solution for this problem with the BT401.

PS.  The link to your website seems suspicious, it opens your page for a few seconds then opens some susupicous looking pages !

AScha.3
Super User
December 21, 2025

Hi, 

1. you again... :)

2. ASFL1-12.288MHZ is a oscillator, yes, just needs 3v3 and it will output 12.xx MHz .

3. You pic is bad/wrong: L433 master receive means: all arrows go from BT401 to the L433/SAI , as BT401 is "master" here, sending out BCK, LRCK , DAT .

4. you need no extra clock then, because its coming from BT401 and you cannot change the clock to any other source.  

5. > But the BT401 either requires multiple attempts to start playing 

Problem could be anything...first: IS bt401 master ? check with a scope, what happens on its output BCK, LRCK , DAT . I dont know, how you /or the BT chips handle a not existing connection , until you connect and send data.

So the problem might be: BT connection has to be stable and without dropouts, then output to dac should be fine.

Until stable data stream from bt401 is established , you should mute the sound output, as it will be useless noise.

"If you feel a post has answered your question, please click ""Accept as Solution""."
freeflyerAuthor
Senior II
December 21, 2025

Hi AScha.3, yes me again :)

I have got everything working nicely, other than the issue with the bluetooth receiver.

When we last discussed this, I had the BT401 as a master I2S and the STM32 as a slave I2S.

However, I had to swap this around because the BT401 I2S clocks were intermittent at powerup which meant the voice prompt (stored in external flash connected to the STM32 via SPI with DMA) which is called at power up stuttered.

In fact its a better solution to use the STM32 as the I2S master, because it removes dependancy on the BT401 to generate the I2s clocks.  This means that the voice prompts (which are critical to the system) will work even if the BT401 fails for some reason.

The STM32 outputs the bit clock and left/right clock to the BT401 and amplifier, the BT401 outputs data to the STM32 and the STM32 outputs data to the amplifier.

Below is the SAI configuratoin which should align with the block diagram...

freeflyer_0-1766345144358.png

 

This is all working correctly, other than the issue with playing audio from the BT401.

AScha.3
Super User
December 21, 2025

Hi,

i dont know, how the BT audio doing this - you have to search/read : the problem : who is the master (of clock for play audio) ; see , its always same problem: as long as data is handled as "data" , in web or PC ...no problem; if data is "music" or audio, its still data. BUT if it comes to real world -analog- we have to convert, from digital to analog, and this demands the correct time, data is coming to analog. So the last in chain, the DAC , has to get the defined clock rate, 44k1 or 48k ..., and all the line down, where data is coming from, has to adjust to this, to "play" perfect.

But in BT or PC there usually is a device, in PC called mixer, that decides to play ...48kHz . So all down the stream have to adjust to this. Or you can change the "master clock source" to ...the DAC , but this needs special adjustment in the transmission and devices...

So : can the BT be slave (for the data rate)? and the master clock coming from the L433 ? check this.

+

Imagine simple problem, i got when playing MP3 from web: my device has its clock from a crystal, making 44k1 audio. The server somewhere on this planet has its own clock , also from a crystal, sending data for "44k1 rate" , when i order next packet...etc. BUT crystals have not infinite precision, so my crystal might be 1/100000 faster than the server's crystal. Nothing happens, just i want more data from the "future" - until the limit of some buffer setting in the server is reached, maybe after 2 h continuous stream playing. Now the server will denie more fast/future data, and i have to adjust the timing in some way. Usually just a "dropout", and it will go on until again times are drifted apart too much. Or you make some intelligent adjustment, like inserting samples from time to time, to sync the "time" to the server.

 

"If you feel a post has answered your question, please click ""Accept as Solution""."
freeflyerAuthor
Senior II
December 23, 2025

I have fitted the ASFL1-12.288MHZ-EC-T but the STM32 is no longer generating the I2S clocks (bit clock & left/right clock) so my I2S audio has completely stopped working :(

The output of the ASFL1 is connected to pin PA0 of the STM32.

In CubeMX I enabled SAI Extern clock...

freeflyer_1-1766501921315.png

The SAI clock is configured to use SAI EXT...

freeflyer_0-1766501762268.png

 

I have checked the 12.288MHz output on a scope....

 

freeflyer_2-1766502115763.png

 

For reference, below is the clock configuration when I2S did work (with the exception of the BT issues).  This is when I used the internal MSI RC to generate the 12.288MHz clock...

freeflyer_3-1766502234883.png

 

 

The only thing that has changed is the SAI clock source, instead of using the internal MSI RC it is using the external SAI pin.

So why does it not work with the external SAI 12.288MHz clock ?

freeflyerAuthor
Senior II
December 23, 2025

Is this a clue ?

If so it makes no sense, because it implies that SAI_EXTCLK on pin PA0 is an output due to the fact the GPIO mode is push/pull....

 

freeflyer_0-1766519977934.png

 

So if its an output, how can it be used to clock the SAI peripheral ???

 

mƎALLEm
Technical Moderator
December 26, 2025

Hello @freeflyer ,

Regarding this statement:


@freeflyer wrote:

The ASFL1-12.288MHZ-EC-T seems to be an all in one device, you just provide power and it generates the output clock.  So its not like a crystal which needs a special drive circuit ?

I have read the application note AN2867 Recommended resonators for STM32 MCUs/MPUs, but its complicated and just confused me.


ASFL1-12.288MHZ-EC-T is a crystal oscillator (XO) according to its datasheet: while AN2867 is treating the case of crystals (XTAL) and resonators.

In other hand, if AN2867 looks complicated, I suggest to refer to this article: How to select a compatible crystal and load capacitors for STM32 with layout guidelines, a simplified version of that application note ;)

"To give better visibility on the answered topics, please click on ""Accept as Solution"" on the reply which solved your issue or answered your question."
Associate
December 26, 2025

The MSI RC + PLL is fine for some codecs, but Bluetooth audio can be much more sensitive. An external low-jitter clock is the right thing to test. The ASFL1 you linked is an oscillator, not a crystal, so it doesn’t need a load network just power and proper routing to the SAI clock input. That makes it a good option for ruling out clock quality issues. Using the internal RC here can feel like a ruleta de la suerte online with BT audio, so a clean external clock should quickly confirm whether jitter is the root cause.

freeflyerAuthor
Senior II
December 26, 2025

Yes I have already done this, I tried to feed the 12.288 MHz from the osillator into the SAI EXTCLOCK pin but it did not work.  So instead I fed it into the HSE pin and it worked, but I still had the same issues with the BT401 playback.  So I concluded that the issue is not due to clock drift/jitter of the MSI, because the issue still occurs when I use the oscillator

freeflyerAuthor
Senior II
December 27, 2025

I found the reason why the SAI EXT CLOCK was not being configured.

The generated code in the file stm32l4xx_hal_msp.c configures all the periperhal clocks.

When initialising each peripheral, the clock selection is defined by PeriphClkInit.PeriphClockSelection.

But for some reason, when initialising the SAI peripheral (HAL_SAI_MspIni) there is no value assigned to PeriphClkInit.PeriphClockSelection

A value is assigned to PeriphClkInit.Sai1ClockSelection (RCC_SAI1CLKSOURCE_PIN) but because PeriphClkInit.PeriphClockSelection is zero the SAI clock peripheral never gets configured

So I manually added the line (for SAI block B)... 

 

PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SAI1;

 

So is this a bug ?  All other periphals (e.g. USB, UART, I2C etc) are assigned with a value for PeriphClkInit.PeriphClockSelection with the exception of the SAI.

HAL_SAI_MspIni is shown below (with my manually added line for block B)...

void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai)
{

 GPIO_InitTypeDef GPIO_InitStruct;
 RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/* SAI1 */
 if(hsai->Instance==SAI1_Block_A)
 {
 /* Peripheral clock enable */

 /** Initializes the peripherals clock
 */
 PeriphClkInit.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PIN;
 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
 {
 Error_Handler();
 }

 if (SAI1_client == 0)
 {
 __HAL_RCC_SAI1_CLK_ENABLE();
 }
 SAI1_client ++;

 /**SAI1_A_Block_A GPIO Configuration
 PB13 ------> SAI1_SCK_A
 PA9 ------> SAI1_FS_A
 PA10 ------> SAI1_SD_A
 */
 GPIO_InitStruct.Pin = BT_I2S_SCK_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 GPIO_InitStruct.Alternate = GPIO_AF13_SAI1;
 HAL_GPIO_Init(BT_I2S_SCK_GPIO_Port, &GPIO_InitStruct);

 GPIO_InitStruct.Pin = BT_I2S_FS_Pin|BT_I2S_SD_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 GPIO_InitStruct.Alternate = GPIO_AF13_SAI1;
 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

 /* Peripheral DMA init*/

 hdma_sai1_a.Instance = DMA2_Channel1;
 hdma_sai1_a.Init.Request = DMA_REQUEST_1;
 hdma_sai1_a.Init.Direction = DMA_PERIPH_TO_MEMORY;
 hdma_sai1_a.Init.PeriphInc = DMA_PINC_DISABLE;
 hdma_sai1_a.Init.MemInc = DMA_MINC_ENABLE;
 hdma_sai1_a.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
 hdma_sai1_a.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
 hdma_sai1_a.Init.Mode = DMA_CIRCULAR;
 hdma_sai1_a.Init.Priority = DMA_PRIORITY_VERY_HIGH;
 if (HAL_DMA_Init(&hdma_sai1_a) != HAL_OK)
 {
 Error_Handler();
 }

 /* Several peripheral DMA handle pointers point to the same DMA handle.
 Be aware that there is only one channel to perform all the requested DMAs. */
 __HAL_LINKDMA(hsai,hdmarx,hdma_sai1_a);

 __HAL_LINKDMA(hsai,hdmatx,hdma_sai1_a);

 }
 if(hsai->Instance==SAI1_Block_B)
 {
 /* Peripheral clock enable */

 /** Initializes the peripherals clock
 */
 PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SAI1; // MANUALLY ADDED 
 PeriphClkInit.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PIN;
 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
 {
 Error_Handler();
 }

 if (SAI1_client == 0)
 {
 __HAL_RCC_SAI1_CLK_ENABLE();
 }
 SAI1_client ++;

 /**SAI1_B_Block_B GPIO Configuration
 PA4 ------> SAI1_FS_B
 PB3 (JTDO-TRACESWO) ------> SAI1_SCK_B
 PB5 ------> SAI1_SD_B
 */
 GPIO_InitStruct.Pin = AMP_I2S_FS_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 GPIO_InitStruct.Alternate = GPIO_AF13_SAI1;
 HAL_GPIO_Init(AMP_I2S_FS_GPIO_Port, &GPIO_InitStruct);

 GPIO_InitStruct.Pin = AMP_I2S_SCK_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 GPIO_InitStruct.Alternate = GPIO_AF13_SAI1;
 HAL_GPIO_Init(AMP_I2S_SCK_GPIO_Port, &GPIO_InitStruct);

 GPIO_InitStruct.Pin = AMP_I2S_SD_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_PULLDOWN;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 GPIO_InitStruct.Alternate = GPIO_AF13_SAI1;
 HAL_GPIO_Init(AMP_I2S_SD_GPIO_Port, &GPIO_InitStruct);

 /* Peripheral DMA init*/

 hdma_sai1_b.Instance = DMA2_Channel2;
 hdma_sai1_b.Init.Request = DMA_REQUEST_1;
 hdma_sai1_b.Init.Direction = DMA_MEMORY_TO_PERIPH;
 hdma_sai1_b.Init.PeriphInc = DMA_PINC_DISABLE;
 hdma_sai1_b.Init.MemInc = DMA_MINC_ENABLE;
 hdma_sai1_b.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
 hdma_sai1_b.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
 hdma_sai1_b.Init.Mode = DMA_CIRCULAR;
 hdma_sai1_b.Init.Priority = DMA_PRIORITY_VERY_HIGH;
 if (HAL_DMA_Init(&hdma_sai1_b) != HAL_OK)
 {
 Error_Handler();
 }

 /* Several peripheral DMA handle pointers point to the same DMA handle.
 Be aware that there is only one channel to perform all the requested DMAs. */
 __HAL_LINKDMA(hsai,hdmarx,hdma_sai1_b);
 __HAL_LINKDMA(hsai,hdmatx,hdma_sai1_b);
 }
}

 

December 28, 2025

It sounds like you’re running into issues because the MSI RC clock inside the STM32L433 has too much jitter for your BT401. That can definitely cause the kind of problems you’re seeing, like screeching sounds or needing multiple tries to start playback.

Yes, the ASFL1-12.288MHZ-EC-T should work for your setup. It’s a crystal oscillator with a built-in circuit, so you don’t need a separate drive circuit like a normal crystal. You just connect power and ground, and it gives a clean 12.288 MHz output, which should be much more stable than the internal MSI RC.

Using it as the SAI external clock should help reduce jitter and may fix the BT401 playback issues. Make sure your connections are solid and keep the traces short if possible to avoid introducing extra noise.

The main thing is that your MAX98357A amplifier might still work with the internal MSI clock because it’s more tolerant of jitter, but the BT401 seems to need a precise clock. Switching to the ASFL1 oscillator is a pinterest video downloader good next step.

Hope this was helpful!