Home > ARM > STM32 – Internal 8MHz Clock Setup Routine

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);
}
Categories: ARM Tags:
  1. Grant
    March 25th, 2013 at 15:02 | #1

    Hi there – thanks for this. Worked perfectly. Clear comments. Thank you!

  2. June 14th, 2014 at 15:41 | #2

    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

  3. June 15th, 2014 at 09:30 | #3

    @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_Div2,RCC_CFGR_PLLMULL12);  // (8 MHz / 2) * 12 = 48 MHz
    RCC_PLLConfig(RCC_CFGR_PLLSRC_HSI_Div1,RCC_CFGR_PLLMULL6);  // (8 MHz / 1) * 6 = 48 MHz

    Best regards
    Thomas Jespersen

  4. June 15th, 2014 at 16:38 | #4

    @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

  5. June 27th, 2014 at 15:58 | #5

    @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

  6. kaushal
    November 2nd, 2015 at 08:03 | #6

    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

  1. December 5th, 2010 at 22:09 | #1