STM32 – Internal 8MHz Clock Setup Routine
Here is the setup code to use the internal 8MHz clock – but with the internal clock, we are only able to get a max frequency of 36MHz.
void clock_init(){
/*Configure all clocks to max for best performance.
* If there are EMI, power, or noise problems, try slowing the clocks*/
/* First set the flash latency to work with our clock*/
/*000 Zero wait state, if 0 MHz < SYSCLK <= 24 MHz
001 One wait state, if 24 MHz < SYSCLK <= 48 MHz
010 Two wait states, if 48 MHz < SYSCLK <= 72 MHz */
FLASH_SetLatency(FLASH_Latency_1);
/* Start with HSI clock (internal 8mhz), divide by 2 and multiply by 9 to
* get maximum allowed frequency: 36Mhz
* Enable PLL, wait till it's stable, then select it as system clock*/
RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_9);
RCC_PLLCmd(ENABLE);
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {}
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
/* Set HCLK, PCLK1, and PCLK2 to SCLK (these are default */
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div1);
RCC_PCLK2Config(RCC_HCLK_Div1);
/* Set ADC clk to 9MHz (14MHz max, 18MHz default)*/
RCC_ADCCLKConfig(RCC_PCLK2_Div4);
/*To save power, use below functions to stop the clock to ceratin
* peripherals
* RCC_AHBPeriphClockCmd
*/
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ALL, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_ALL, ENABLE);
}
/*Configure all clocks to max for best performance.
* If there are EMI, power, or noise problems, try slowing the clocks*/
/* First set the flash latency to work with our clock*/
/*000 Zero wait state, if 0 MHz < SYSCLK <= 24 MHz
001 One wait state, if 24 MHz < SYSCLK <= 48 MHz
010 Two wait states, if 48 MHz < SYSCLK <= 72 MHz */
FLASH_SetLatency(FLASH_Latency_1);
/* Start with HSI clock (internal 8mhz), divide by 2 and multiply by 9 to
* get maximum allowed frequency: 36Mhz
* Enable PLL, wait till it's stable, then select it as system clock*/
RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_9);
RCC_PLLCmd(ENABLE);
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {}
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
/* Set HCLK, PCLK1, and PCLK2 to SCLK (these are default */
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div1);
RCC_PCLK2Config(RCC_HCLK_Div1);
/* Set ADC clk to 9MHz (14MHz max, 18MHz default)*/
RCC_ADCCLKConfig(RCC_PCLK2_Div4);
/*To save power, use below functions to stop the clock to ceratin
* peripherals
* RCC_AHBPeriphClockCmd
*/
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ALL, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_ALL, ENABLE);
}
Hi there – thanks for this. Worked perfectly. Clear comments. Thank you!
Hi, very helpful code and explanation, thank you!
I have a code which is a bit different, I want to learn if I have any mistake on it.
RCC_DeInit();
RCC_HSEConfig(RCC_HSE_OFF);
RCC_HSICmd(ENABLE);
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
FLASH_SetLatency(FLASH_Latency_1);
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div1); // div 2 ? apb1 max 36mhz
RCC_PCLK2Config(RCC_HCLK_Div1);
RCC_PLLConfig(RCC_CFGR_PLLSRC_HSI_Div2,RCC_CFGR_PLLMULL12);
RCC_PLLCmd(ENABLE);
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
while (RCC_GetSYSCLKSource() != 0x08);
What if I write instead? Is it the same?
RCC_PLLConfig(RCC_CFGR_PLLSRC_HSI_Div1,RCC_CFGR_PLLMULL6);
My bus clock sets are before PLL, is it problem?
Thanks in advence
@karttasarimi
The RCC_PLLConfig function is for configuring the PLL controller that takes care of the “multiplying” of the clock frequency.
As mentioned in the post we would like to get the maximum frequency possible, which is 36 MHz. As the internal oscillator, PLL source RCC_CFGR_PLLSRC_HSI, is 8 MHz, we need to divide this by 2 and multiply with 9 to get the 36 MHz.
In your case you are trying to get 48 MHz which won’t work.
Though for your questions regarding the use of either command, the two commands should theoretically give the same output frequency:
RCC_PLLConfig(RCC_CFGR_PLLSRC_HSI_Div1,RCC_CFGR_PLLMULL6); // (8 MHz / 1) * 6 = 48 MHz
Best regards
Thomas Jespersen
@Thomas, thanks for the answer. My processor is f103 and It can generate 48Mhz using HSI cause it has usb, so USB works on HSI in practise.
I have another simple question;
Can I use the RCC_AdjustHSICalibrationValue(20); function in whereever I want? I mean I will call this function in runtime after clock configurations. Is that legal? I’ve tried it, I didn’t see any problem but not sure does it work actually, somehow the frequency is the same…
Thanks in advance
@karttasarimi
Ahh sure, I forgot about the USB requirement of the 48MHz.
I wouldn’t suggest calling the Adjust Calibration value method more than once, just in the beginning and initialization of the device.
I haven’t seen any places where it says it’s “illegal” but I don’t think the processor will be able to do any changes to the calibration when the crystal/oscillator has stabilized.
Regards Thomas
hello thomas and karttasarimi, i read your conversation and it helped me a lot. i want to generate 72 Mhz clock using external crystal (HSE) for USART application. i am using same f103 for this application. is it possible? if yes then please guide me through steps as you have done earlier @ Thomas