如何实现使用HSE和PLL配置STM32G474时钟树

如何实现使用HSE和PLL配置STM32G474时钟树?

再好的库都需要配置时钟树,不管是标准库,还是HAL库,如果工程模板没有配置好RCC时钟,还是需要我们自己动手配置,即使工程模板配置好了,也不一定是我们需要的时钟。特别是需要PWM输出控制时,如数字电源,在STM32G474单片机中,配置时钟树就显得尤其重要。

1、时钟树

STM32G474时钟树如下,先看图,然后再看代码。

2、程序

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST);
    //配置主内部调节器输出电压
    //修改PWR->CR1寄存器bit10:9(VOS[1:0]),VOS[1:0]=01b,电压缩放范围选择"Range 1"
    //Configure the main internal regulator output voltage

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    //记录修改对象,告诉后面的函数将要对“HSE时钟”进行配置
  RCC_OscInitStruct.HSEState      = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState  = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM      = RCC_PLLM_DIV2;
    //RCC_PLLCFGR寄存器bit7:4(PLLM[3:0]),PLLM[3:0]=0001b,PLLM的值为2
  RCC_OscInitStruct.PLL.PLLN = 85;
    //RCC_PLLCFGR寄存器bit14:8(PLLN[3:0]),PLLN[6:0]=0x55,PLLN为的值为85
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    //RCC_PLLCFGR寄存器bit17(PLLP),PLLP=1,PLLP的分频值为17
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
    //RCC_PLLCFGR寄存器bit22:21(PLLQ[1:0]),PLLQ[1:0]=01,PLLQ的分频值为2
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
    //RCC_PLLCFGR寄存器bit26:25(PLLR[1:0]),PLLR[1:0]=01,PLLR的分频值为2
/*
f(VCO clock) = (HSE_VALUE / PLLM) * PLLN
f(PLL_P) = f(VCO clock) / PLLP
f(PLL_Q) = f(VCO clock) / PLLQ
f(PLL_R) = f(VCO clock) / PLLR
HSE_VALUE = 8000000,外部晶振为8MHz
PLL_VCO = (HSE_VALUE / PLLM) * PLLN = (8000000/2)*85=340000000Hz=340MHz
SYSCLK = PLL_VCO / PLLR = 340000000 / 2 = 170000000Hz = 170MHz
PLL “P” clock = PLL_VCO / 2 = 340000000/2 =170000000Hz = 170MHz
PLL “Q” output clock frequency = VCO frequency / PLLQ = 340000000 / 2 = 170000000Hz = 170MHz
*/

  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {//配置“HSE时钟”和“PLL时钟”
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    //记录修改对象,告诉后面的函数将要修改HCLK,SYSCLK,PCLK1,PCLK2等时钟
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    //记录修改对象,告诉后面的函数将PLLCLK用作系统时钟
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    //AHB时钟(HCLK)的分频值
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
    //配置RCC_CFGR寄存器bit10:8(PPRE1[2:0]),APB1时钟(PCLK1)的分频值
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    //配置RCC_CFGR寄存器bit13:11(PPRE2[2:0]),APB2时钟(PCLK2)的分频值
    //APB2外设:HRTIM,TIM1,TIM8,TIM15,TIM16,TIM17,TIM20,SPI1,SPI4,USART1,SAI1,SYSCFG/COMP/OPAMP/VREFBUF

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
  {//配置HCLK,SYSCLK,PCLK1,PCLK2时钟
        //HCLK为170MHz,PCLK1时钟为170MHz,PCLK2时钟为170MHz

    Error_Handler();
  }

    SystemCoreClockUpdate();//更新SystemCoreClock的值
}

 

重点部分,和HSE和PLL有关的,使用中文注释

/**
  * @brief  Initialize the RCC Oscillators according to the specified parameters in the
  *         RCC_OscInitTypeDef.
  * @param  RCC_OscInitStruct  pointer to an RCC_OscInitTypeDef structure that
  *         contains the configuration information for the RCC Oscillators.
  * @note   The PLL is not disabled when used as system clock.
  * @note   Transitions LSE Bypass to LSE On and LSE On to LSE Bypass are not
  *         supported by this macro. User should request a transition to LSE Off
  *         first and then LSE On or LSE Bypass.
  * @note   Transition HSE Bypass to HSE On and HSE On to HSE Bypass are not
  *         supported by this macro. User should request a transition to HSE Off
  *         first and then HSE On or HSE Bypass.
  * @retval HAL status
  */
//函数功能:配置“HSE时钟”和“PLL时钟”

HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef  *RCC_OscInitStruct)
{
  uint32_t tickstart;
  uint32_t temp_sysclksrc;
  uint32_t temp_pllckcfg;

  /* Check Null pointer */
  if (RCC_OscInitStruct == NULL)
  {
    return HAL_ERROR;
  }

  /* Check the parameters */
  assert_param(IS_RCC_OSCILLATORTYPE(RCC_OscInitStruct->OscillatorType));

  /*------------------------------- HSE Configuration ------------------------*/
  if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSE) == RCC_OSCILLATORTYPE_HSE)
  {
    /* Check the parameters */
    assert_param(IS_RCC_HSE(RCC_OscInitStruct->HSEState));

    temp_sysclksrc = __HAL_RCC_GET_SYSCLK_SOURCE();
    //读取RCC->CFGR寄存器的bit3:2(SWS[1:0])
    //SWS[1:0]=01b,表示HSI16作为系统时钟
    //SWS[1:0]=10b,表示HSE作为系统时钟
    //SWS[1:0]=11b,表示PLL作为系统时钟,RCC_CFGR_SWS_PLL

    temp_pllckcfg = __HAL_RCC_GET_PLL_OSCSOURCE();
    //读RCC->PLLCFGR寄存器bit1:0(PLLSRC[1:0])
    //PLLSRC[1:0]=10b,HSI16作为PLL输入时钟
    //PLLSRC[1:0]=11b,HSE作为PLL输入时钟,RCC_PLLSOURCE_HSE

    /* When the HSE is used as system clock or clock source for PLL in these cases it is not allowed to be disabled */
    if (((temp_sysclksrc == RCC_CFGR_SWS_PLL) && (temp_pllckcfg == RCC_PLLSOURCE_HSE)) || (temp_sysclksrc == RCC_CFGR_SWS_HSE))
    {
      if ((READ_BIT(RCC->CR, RCC_CR_HSERDY) != 0U) && (RCC_OscInitStruct->HSEState == RCC_HSE_OFF))
      {
        return HAL_ERROR;
      }
    }
    else
    {
      /* Set the new HSE configuration ---------------------------------------*/
      __HAL_RCC_HSE_CONFIG(RCC_OscInitStruct->HSEState);
            //设置RCC->CR寄存器的bit16(HSEON位),令HSEON=1,HSE时钟使能

      /* Check the HSE State */
      if (RCC_OscInitStruct->HSEState != RCC_HSE_OFF)
      {
        /* Get Start Tick*/
        tickstart = HAL_GetTick();//读滴答定时器

        /* Wait till HSE is ready */
        while (READ_BIT(RCC->CR, RCC_CR_HSERDY) == 0U)
        {//读RCC->CR寄存器的bit17(HSERDY位),当HSERDY=1时,表示HSE时钟准备就绪
          if ((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE)
          {
            return HAL_TIMEOUT;
          }
        }
      }
      else
      {
        /* Get Start Tick*/
        tickstart = HAL_GetTick();

        /* Wait till HSE is disabled */
        while (READ_BIT(RCC->CR, RCC_CR_HSERDY) != 0U)
        {
          if ((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE)
          {
            return HAL_TIMEOUT;
          }
        }
      }
    }
  }
  /*----------------------------- HSI Configuration --------------------------*/
  if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI)
  {
    /* Check the parameters */
    assert_param(IS_RCC_HSI(RCC_OscInitStruct->HSIState));
    assert_param(IS_RCC_HSI_CALIBRATION_VALUE(RCC_OscInitStruct->HSICalibrationValue));

    /* Check if HSI is used as system clock or as PLL source when PLL is selected as system clock */
    temp_sysclksrc = __HAL_RCC_GET_SYSCLK_SOURCE();
    temp_pllckcfg = __HAL_RCC_GET_PLL_OSCSOURCE();
    if (((temp_sysclksrc == RCC_CFGR_SWS_PLL) && (temp_pllckcfg == RCC_PLLSOURCE_HSI)) || (temp_sysclksrc == RCC_CFGR_SWS_HSI))
    {
      /* When HSI is used as system clock it will not be disabled */
      if ((READ_BIT(RCC->CR, RCC_CR_HSIRDY) != 0U) && (RCC_OscInitStruct->HSIState == RCC_HSI_OFF))
      {
        return HAL_ERROR;
      }
      /* Otherwise, just the calibration is allowed */
      else
      {
        /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/
        __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue);

        /* Adapt Systick interrupt period */
        if (HAL_InitTick(uwTickPrio) != HAL_OK)
        {
          return HAL_ERROR;
        }
      }
    }
    else
    {
      /* Check the HSI State */
      if (RCC_OscInitStruct->HSIState != RCC_HSI_OFF)
      {
        /* Enable the Internal High Speed oscillator (HSI). */
        __HAL_RCC_HSI_ENABLE();

        /* Get Start Tick*/
        tickstart = HAL_GetTick();

        /* Wait till HSI is ready */
        while (READ_BIT(RCC->CR, RCC_CR_HSIRDY) == 0U)
        {
          if ((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE)
          {
            return HAL_TIMEOUT;
          }
        }

        /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/
        __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue);
      }
      else
      {
        /* Disable the Internal High Speed oscillator (HSI). */
        __HAL_RCC_HSI_DISABLE();

        /* Get Start Tick*/
        tickstart = HAL_GetTick();

        /* Wait till HSI is disabled */
        while (READ_BIT(RCC->CR, RCC_CR_HSIRDY) != 0U)
        {
          if ((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE)
          {
            return HAL_TIMEOUT;
          }
        }
      }
    }
  }
  /*------------------------------ LSI Configuration -------------------------*/
  if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSI) == RCC_OSCILLATORTYPE_LSI)
  {
    /* Check the parameters */
    assert_param(IS_RCC_LSI(RCC_OscInitStruct->LSIState));

    /* Check the LSI State */
    if(RCC_OscInitStruct->LSIState != RCC_LSI_OFF)
    {
      /* Enable the Internal Low Speed oscillator (LSI). */
      __HAL_RCC_LSI_ENABLE();

      /* Get Start Tick*/
      tickstart = HAL_GetTick();

      /* Wait till LSI is ready */
      while (READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) == 0U)
      {
        if ((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE)
        {
          return HAL_TIMEOUT;
        }
      }
    }
    else
    {
      /* Disable the Internal Low Speed oscillator (LSI). */
      __HAL_RCC_LSI_DISABLE();

      /* Get Start Tick*/
      tickstart = HAL_GetTick();

      /* Wait till LSI is disabled */
      while(READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) != 0U)
      {
        if((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE)
        {
          return HAL_TIMEOUT;
        }
      }
    }
  }
  /*------------------------------ LSE Configuration -------------------------*/
  if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE)
  {
    FlagStatus       pwrclkchanged = RESET;

    /* Check the parameters */
    assert_param(IS_RCC_LSE(RCC_OscInitStruct->LSEState));

    /* Update LSE configuration in Backup Domain control register    */
    /* Requires to enable write access to Backup Domain if necessary */

    if (__HAL_RCC_PWR_IS_CLK_DISABLED() != 0U)
    {
      __HAL_RCC_PWR_CLK_ENABLE();
      pwrclkchanged = SET;
    }

    if (HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP))
    {
      /* Enable write access to Backup domain */
      SET_BIT(PWR->CR1, PWR_CR1_DBP);

      /* Wait for Backup domain Write protection disable */
      tickstart = HAL_GetTick();

      while (HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP))
      {
        if ((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
        {
          return HAL_TIMEOUT;
        }
      }
    }

    /* Set the new LSE configuration -----------------------------------------*/
    __HAL_RCC_LSE_CONFIG(RCC_OscInitStruct->LSEState);

    /* Check the LSE State */
    if (RCC_OscInitStruct->LSEState != RCC_LSE_OFF)
    {
      /* Get Start Tick*/
      tickstart = HAL_GetTick();

      /* Wait till LSE is ready */
      while (READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == 0U)
      {
        if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
        {
          return HAL_TIMEOUT;
        }
      }
    }
    else
    {
      /* Get Start Tick*/
      tickstart = HAL_GetTick();

      /* Wait till LSE is disabled */
      while (READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) != 0U)
      {
        if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
        {
          return HAL_TIMEOUT;
        }
      }
    }

    /* Restore clock configuration if changed */
    if (pwrclkchanged == SET)
    {
      __HAL_RCC_PWR_CLK_DISABLE();
    }
  }

  /*------------------------------ HSI48 Configuration -----------------------*/
  if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI48) == RCC_OSCILLATORTYPE_HSI48)
  {
    /* Check the parameters */
    assert_param(IS_RCC_HSI48(RCC_OscInitStruct->HSI48State));

    /* Check the HSI48 State */
    if(RCC_OscInitStruct->HSI48State != RCC_HSI48_OFF)
    {
      /* Enable the Internal Low Speed oscillator (HSI48). */
      __HAL_RCC_HSI48_ENABLE();

      /* Get Start Tick*/
      tickstart = HAL_GetTick();

      /* Wait till HSI48 is ready */
      while(READ_BIT(RCC->CRRCR, RCC_CRRCR_HSI48RDY) == 0U)
      {
        if((HAL_GetTick() - tickstart) > HSI48_TIMEOUT_VALUE)
        {
          return HAL_TIMEOUT;
        }
      }
    }
    else
    {
      /* Disable the Internal Low Speed oscillator (HSI48). */
      __HAL_RCC_HSI48_DISABLE();

      /* Get Start Tick*/
      tickstart = HAL_GetTick();

      /* Wait till HSI48 is disabled */
      while(READ_BIT(RCC->CRRCR, RCC_CRRCR_HSI48RDY) != 0U)
      {
        if((HAL_GetTick() - tickstart) > HSI48_TIMEOUT_VALUE)
        {
          return HAL_TIMEOUT;
        }
      }
    }
  }

  /*-------------------------------- PLL Configuration -----------------------*/
  /* Check the parameters */

  assert_param(IS_RCC_PLL(RCC_OscInitStruct->PLL.PLLState));

  if (RCC_OscInitStruct->PLL.PLLState != RCC_PLL_NONE)
  {
    /* Check if the PLL is used as system clock or not */
    if (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL)
    {//读取RCC->CFGR寄存器的bit3:2(SWS[1:0])
     //SWS[1:0]=01b,表示HSI16作为系统时钟
     //SWS[1:0]=10b,表示HSE作为系统时钟
     //SWS[1:0]=11b,表示PLL作为系统时钟

      if (RCC_OscInitStruct->PLL.PLLState == RCC_PLL_ON)
      {
        /* Check the parameters */
        assert_param(IS_RCC_PLLSOURCE(RCC_OscInitStruct->PLL.PLLSource));
        assert_param(IS_RCC_PLLM_VALUE(RCC_OscInitStruct->PLL.PLLM));
        assert_param(IS_RCC_PLLN_VALUE(RCC_OscInitStruct->PLL.PLLN));
        assert_param(IS_RCC_PLLP_VALUE(RCC_OscInitStruct->PLL.PLLP));
        assert_param(IS_RCC_PLLQ_VALUE(RCC_OscInitStruct->PLL.PLLQ));
        assert_param(IS_RCC_PLLR_VALUE(RCC_OscInitStruct->PLL.PLLR));

        __HAL_RCC_PLL_DISABLE();
                //设置RCC->CR寄存器的bit24(PLLON位),令PLLON=0,PLL时钟不使能
                //Disable the main PLL.

        /* Get Start Tick*/
        tickstart = HAL_GetTick();

        /* Wait till PLL is ready */
        while (READ_BIT(RCC->CR, RCC_CR_PLLRDY) != 0U)
        {//读RCC->CR寄存器的bit25(PLLRDY位),当PLLRDY=1,PLL时钟上锁
          if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
          {
            return HAL_TIMEOUT;
          }
        }

        /* Configure the main PLL clock source, multiplication and division factors. */
        __HAL_RCC_PLL_CONFIG(RCC_OscInitStruct->PLL.PLLSource,
                             RCC_OscInitStruct->PLL.PLLM,
                             RCC_OscInitStruct->PLL.PLLN,
                             RCC_OscInitStruct->PLL.PLLP,
                             RCC_OscInitStruct->PLL.PLLQ,
                             RCC_OscInitStruct->PLL.PLLR);
                //修改RCC->PLLCFGR寄存器bit7:4(PLLM[3:0]),bit14:8(PLLN[6:0]),bit22:21(PLLQ[1:0]),bit26:25(PLLR[1:0])
        /*
                  f(VCO clock) = f(PLL clock input) × (PLLN / PLLM)
          f(PLL_P) = f(VCO clock) / PLLP
          f(PLL_Q) = f(VCO clock) / PLLQ
          f(PLL_R) = f(VCO clock) / PLLR
                */

        /* Enable the main PLL. */
        __HAL_RCC_PLL_ENABLE();

//设置RCC->CR寄存器的bit24(PLLON位),令PLLON=1,PLL时钟使能

        /* Enable PLL System Clock output. */
         __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SYSCLK);
 //修改RCC->PLLCFGR寄存器bit24(PLLREN),令PLLREN=1,PLL “R” clock output enable

        /* Get Start Tick*/
        tickstart = HAL_GetTick();

        /* Wait till PLL is ready */
        while (READ_BIT(RCC->CR, RCC_CR_PLLRDY) == 0U)
        {//读RCC->CR寄存器的bit25(PLLRDY位),当PLLRDY=1,PLL时钟上锁
          if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
          {
            return HAL_TIMEOUT;
          }
        }
      }
      else
      {
        /* Disable the main PLL. */
        __HAL_RCC_PLL_DISABLE();

        /* Disable all PLL outputs to save power if no PLLs on */
          MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, RCC_PLLSOURCE_NONE);
        __HAL_RCC_PLLCLKOUT_DISABLE(RCC_PLL_SYSCLK | RCC_PLL_48M1CLK | RCC_PLL_ADCCLK);

        /* Get Start Tick*/
        tickstart = HAL_GetTick();

        /* Wait till PLL is disabled */
        while (READ_BIT(RCC->CR, RCC_CR_PLLRDY) != 0U)
        {
          if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
          {
            return HAL_TIMEOUT;
          }
        }
      }
    }
    else
    {
      /* Check if there is a request to disable the PLL used as System clock source */
      if((RCC_OscInitStruct->PLL.PLLState) == RCC_PLL_OFF)
      {
        return HAL_ERROR;
      }
      else
      {
      /* Do not return HAL_ERROR if request repeats the current configuration */
      temp_pllckcfg = RCC->PLLCFGR;
      if((READ_BIT(temp_pllckcfg, RCC_PLLCFGR_PLLSRC) != RCC_OscInitStruct->PLL.PLLSource) ||
         (READ_BIT(temp_pllckcfg, RCC_PLLCFGR_PLLM) != (((RCC_OscInitStruct->PLL.PLLM) - 1U) << RCC_PLLCFGR_PLLM_Pos)) ||
         (READ_BIT(temp_pllckcfg, RCC_PLLCFGR_PLLN) != ((RCC_OscInitStruct->PLL.PLLN) << RCC_PLLCFGR_PLLN_Pos)) ||
         (READ_BIT(temp_pllckcfg, RCC_PLLCFGR_PLLPDIV) != ((RCC_OscInitStruct->PLL.PLLP) << RCC_PLLCFGR_PLLPDIV_Pos)) ||
         (READ_BIT(temp_pllckcfg, RCC_PLLCFGR_PLLQ) != ((((RCC_OscInitStruct->PLL.PLLQ) >> 1U) - 1U) << RCC_PLLCFGR_PLLQ_Pos)) ||
         (READ_BIT(temp_pllckcfg, RCC_PLLCFGR_PLLR) != ((((RCC_OscInitStruct->PLL.PLLR) >> 1U) - 1U) << RCC_PLLCFGR_PLLR_Pos)))
      {
        return HAL_ERROR;
      }
    }
  }
  }

  return HAL_OK;
}

/**
  * @brief  Initialize the CPU, AHB and APB busses clocks according to the specified
  *         parameters in the RCC_ClkInitStruct.
  * @param  RCC_ClkInitStruct  pointer to an RCC_OscInitTypeDef structure that
  *         contains the configuration information for the RCC peripheral.
  * @param  FLatency  FLASH Latency
  *          This parameter can be one of the following values:
  *            @arg FLASH_LATENCY_0   FLASH 0 Latency cycle
  *            @arg FLASH_LATENCY_1   FLASH 1 Latency cycle
  *            @arg FLASH_LATENCY_2   FLASH 2 Latency cycles
  *            @arg FLASH_LATENCY_3   FLASH 3 Latency cycles
  *            @arg FLASH_LATENCY_4   FLASH 4 Latency cycles
  *            @arg FLASH_LATENCY_5   FLASH 5 Latency cycles
  *            @arg FLASH_LATENCY_6   FLASH 6 Latency cycles
  *            @arg FLASH_LATENCY_7   FLASH 7 Latency cycles
  *            @arg FLASH_LATENCY_8   FLASH 8 Latency cycles
  *            @arg FLASH_LATENCY_9   FLASH 9 Latency cycles
  *            @arg FLASH_LATENCY_10  FLASH 10 Latency cycles
  *            @arg FLASH_LATENCY_11  FLASH 11 Latency cycles
  *            @arg FLASH_LATENCY_12  FLASH 12 Latency cycles
  *            @arg FLASH_LATENCY_13  FLASH 13 Latency cycles
  *            @arg FLASH_LATENCY_14  FLASH 14 Latency cycles
  *            @arg FLASH_LATENCY_15  FLASH 15 Latency cycles
  *
  * @note   The SystemCoreClock CMSIS variable is used to store System Clock Frequency
  *         and updated by HAL_RCC_GetHCLKFreq() function called within this function
  *
  * @note   The HSI is used by default as system clock source after
  *         startup from Reset, wake-up from STANDBY mode. After restart from Reset,
  *         the HSI frequency is set to its default value 16 MHz.
  *
  * @note   The HSI can be selected as system clock source after
  *         from STOP modes or in case of failure of the HSE used directly or indirectly
  *         as system clock (if the Clock Security System CSS is enabled).
  *
  * @note   A switch from one clock source to another occurs only if the target
  *         clock source is ready (clock stable after startup delay or PLL locked).
  *         If a clock source which is not yet ready is selected, the switch will
  *         occur when the clock source is ready.
  *
  * @note   You can use HAL_RCC_GetClockConfig() function to know which clock is
  *         currently used as system clock source.
  *
  * @note   Depending on the device voltage range, the software has to set correctly
  *         HPRE[3:0] bits to ensure that HCLK not exceed the maximum allowed frequency
  *         (for more details refer to section above "Initialization/de-initialization functions")
  * @retval None
  */

HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef  *RCC_ClkInitStruct, uint32_t FLatency)
{
  uint32_t tickstart;
  uint32_t pllfreq;
  uint32_t hpre = RCC_SYSCLK_DIV1;

  /* Check Null pointer */
  if (RCC_ClkInitStruct == NULL)
  {
    return HAL_ERROR;
  }

  /* Check the parameters */
  assert_param(IS_RCC_CLOCKTYPE(RCC_ClkInitStruct->ClockType));
  assert_param(IS_FLASH_LATENCY(FLatency));

  /* To correctly read data from FLASH memory, the number of wait states (LATENCY)
    must be correctly programmed according to the frequency of the CPU clock
    (HCLK) and the supply voltage of the device. */

  /* Increasing the number of wait states because of higher CPU frequency */
  if (FLatency > __HAL_FLASH_GET_LATENCY())
  {//读取FLASH->ACR寄存器的bit3:0(LATENCY[3:0])
    /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */

    __HAL_FLASH_SET_LATENCY(FLatency);
        //设置FLASH->ACR寄存器的bit3:0(LATENCY[3:0]),令LATENCY[3:0]=FLatency

    /* Check that the new number of wait states is taken into account to access the Flash
    memory by reading the FLASH_ACR register */

    if (__HAL_FLASH_GET_LATENCY() != FLatency)
    {//读取FLASH->ACR寄存器的bit3:0(LATENCY[3:0])
      return HAL_ERROR;
    }
  }

  /*---------SYSCLK系统时钟配置 SYSCLK Configuration ---------*/
  if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_SYSCLK) == RCC_CLOCKTYPE_SYSCLK)
  {
    assert_param(IS_RCC_SYSCLKSOURCE(RCC_ClkInitStruct->SYSCLKSource));

    /* 使用PLL作为系统时钟源,PLL is selected as System Clock Source */
    if (RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLCLK)
    {
      /* Check the PLL ready flag */
      if (READ_BIT(RCC->CR, RCC_CR_PLLRDY) == 0U)
      {//读RCC->CR寄存器的bit25(PLLRDY),PLLRDY=1表示PLL时钟已经就绪
        return HAL_ERROR;
      }
      /* Undershoot management when selection PLL as SYSCLK source and frequency above 80Mhz */
      /* Compute target PLL output frequency */

      pllfreq = RCC_GetSysClockFreqFromPLLSource();//读取系统时钟频率为170MHz

      /* Intermediate step with HCLK prescaler 2 necessary before to go over 80Mhz */
      if(pllfreq > 80000000U)//在超过80MHz之前,需要这个中间步骤将HCLK设置为2分频
      {
        if (((READ_BIT(RCC->CFGR, RCC_CFGR_HPRE) == RCC_SYSCLK_DIV1)) ||
            (((((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK) == RCC_CLOCKTYPE_HCLK) &&
              (RCC_ClkInitStruct->AHBCLKDivider == RCC_SYSCLK_DIV1))))
        {
          MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV2);
//修改RCC->CFGR寄存器bit7:4(HPRE[3:0]),HPRE[3:0]=1000b,设置AHB分频器值为2分频
                    //AHB时钟为系统时钟的2分频,SYSCLK divided by 2
 //HCLK时钟频率为系统时钟的2分频,后面会再次对它进行配置,这里是个中间步骤。

          hpre = RCC_SYSCLK_DIV2;
                    //记录,后面以此为依据来修改;但是本次配置已经指定了"AHB时钟(HCLK)的分频值"
        }
      }
    }
    else
    {
      /* HSE is selected as System Clock Source */
      if (RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE)
      {
        /* Check the HSE ready flag */
        if(READ_BIT(RCC->CR, RCC_CR_HSERDY) == 0U)
        {
          return HAL_ERROR;
        }
      }
      /* HSI is selected as System Clock Source */
      else
      {
        /* Check the HSI ready flag */
        if(READ_BIT(RCC->CR, RCC_CR_HSIRDY) == 0U)
        {
          return HAL_ERROR;
        }
      }
      /* Overshoot management when going down from PLL as SYSCLK source and frequency above 80Mhz */
      pllfreq = HAL_RCC_GetSysClockFreq();

      /* Intermediate step with HCLK prescaler 2 necessary before to go under 80Mhz */
      if(pllfreq > 80000000U)
      {
        MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV2);
        hpre = RCC_SYSCLK_DIV2;
      }

    }

    MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_ClkInitStruct->SYSCLKSource);
        //修改RCC->CFGR寄存器bit1:0(SW[1:0]),令SW[1:0]=11b,PLL被选择为系统时钟

    /* Get Start Tick*/
    tickstart = HAL_GetTick();

    while (__HAL_RCC_GET_SYSCLK_SOURCE() != (RCC_ClkInitStruct->SYSCLKSource << RCC_CFGR_SWS_Pos))
    {
      if ((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
      {
        return HAL_TIMEOUT;
      }
    }
  }

  /*----HCLK时钟配置,HCLK Configuration----*/
  if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK) == RCC_CLOCKTYPE_HCLK)
  {
    /* Set the highest APB divider in order to ensure that we do not go through
       a non-spec phase whatever we decrease or increase HCLK. */

 //设置最高的APB分配器,以确保我们不会经历一个非规范的阶段,无论我们如何减少或增加HCLK
    if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK1) == RCC_CLOCKTYPE_PCLK1)
    {
      MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_HCLK_DIV16);
            //修改RCC->CFGR寄存器bit10:8(PPRE1[2:0]),令PPRE1[2:0]=111b,APB1分频器值为16
        //APB1时钟,PCLK1时钟为HCLK divided by 16,后面会对它进行修改,这里是一个中间步骤;

    }
    if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK2) == RCC_CLOCKTYPE_PCLK2)
    {
      MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, RCC_HCLK_DIV16);
            //修改RCC->CFGR寄存器bit13:11(PPRE2[2:0]),令PPRE2[2:0]=111b,APB2分频器值为16
//APB2时钟,PCLK2时钟为HCLK divided by 16,后面会对它进行修改,这里是一个中间步骤;

            //这个“HAL库”是不是错了?还是有意为之??
    }

    /* Set the new HCLK clock divider */
    assert_param(IS_RCC_HCLK(RCC_ClkInitStruct->AHBCLKDivider));
    MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_ClkInitStruct->AHBCLKDivider);
        //修改RCC->CFGR寄存器bit7:4(HPRE[3:0]),令HPRE[3:0]=0xxxb,AHB分频器值为1
        //HCLK为SYSCLK not divided
        //还记得前面有一个中间步骤吗?这里再次配置HCLK时钟分频器。

  }
  else
  {
    /* Is intermediate HCLK prescaler 2 applied internally, complete with HCLK prescaler 1 */
    if(hpre == RCC_SYSCLK_DIV2)
    {
      MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV1);
    }
  }

  /* Decreasing the number of wait states because of lower CPU frequency */
  if (FLatency < __HAL_FLASH_GET_LATENCY())
  {//读取FLASH->ACR寄存器的bit3:0(LATENCY[3:0])
    /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */

    __HAL_FLASH_SET_LATENCY(FLatency);
        //设置FLASH->ACR寄存器的bit3:0(LATENCY[3:0]),令LATENCY[3:0]=FLatency

    /* Check that the new number of wait states is taken into account to access the Flash
    memory by polling the FLASH_ACR register */

    tickstart = HAL_GetTick();

    while (__HAL_FLASH_GET_LATENCY() != FLatency)
    {
      if ((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
      {
        return HAL_TIMEOUT;
      }
    }
  }

  /*----PCLK1时钟配置,PCLK1 Configuration ----*/
  if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK1) == RCC_CLOCKTYPE_PCLK1)
  {
    assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB1CLKDivider));
    MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_ClkInitStruct->APB1CLKDivider);
        //修改RCC->CFGR寄存器bit10:8(PPRE1[2:0]),令PPRE1[2:0]=0xxb,APB1分频器值为1
        //APB1时钟,PCLK1时钟为HCLK divided by 1
        //记得前面对它配置过一次,用的是16分频,但那只是一个中间步骤,不是最终的配置

  }

  /*----PCLK2时钟配置,PCLK2 Configuration ----*/
  if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK2) == RCC_CLOCKTYPE_PCLK2)
  {
    assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB2CLKDivider));
    MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, ((RCC_ClkInitStruct->APB2CLKDivider) << 3U));
        //修改RCC->CFGR寄存器bit13:11(PPRE2[2:0]),令PPRE2[2:0]=0xxxb,APB2分频器值为1
        //APB2时钟,PCLK2时钟为HCLK divided by 1
        //记得前面对它配置过一次,用的是16分频,但那只是一个中间步骤,不是最终的配置

  }

  /* Update the SystemCoreClock global variable */
  SystemCoreClock = HAL_RCC_GetSysClockFreq() >> (AHBPrescTable[READ_BIT(RCC->CFGR, RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos] & 0x1FU);
    //读取系统时钟频率为170MHz

  /* Configure the source of time base considering new system clocks settings*/
  return HAL_InitTick(uwTickPrio);

//系统时钟更新后,需要重新初始化TIM1,保证TICK定时器按照1秒中断一次;

//我这个是带FreeRTOS系统,所以是重新初始化TIM1,不带系统,就是SysTick定时器
}

/**
  * @brief  Return the SYSCLK frequency.
  *
  * @note   The system frequency computed by this function is not the real
  *         frequency in the chip. It is calculated based on the predefined
  *         constant and the selected clock source:
  * @note     If SYSCLK source is HSI, function returns values based on HSI_VALUE(*)
  * @note     If SYSCLK source is HSE, function returns values based on HSE_VALUE(**)
  * @note     If SYSCLK source is PLL, function returns values based on HSE_VALUE(**),
  *           HSI_VALUE(*) Value multiplied/divided by the PLL factors.
  * @note     (*) HSI_VALUE is a constant defined in stm32g4xx_hal_conf.h file (default value
  *               16 MHz) but the real value may vary depending on the variations
  *               in voltage and temperature.
  * @note     (**) HSE_VALUE is a constant defined in stm32g4xx_hal_conf.h file (default value
  *                8 MHz), user has to ensure that HSE_VALUE is same as the real
  *                frequency of the crystal used. Otherwise, this function may
  *                have wrong result.
  *
  * @note   The result of this function could be not correct when using fractional
  *         value for HSE crystal.
  *
  * @note   This function can be used by the user application to compute the
  *         baudrate for the communication peripherals or configure other parameters.
  *
  * @note   Each time SYSCLK changes, this function must be called to update the
  *         right SYSCLK value. Otherwise, any configuration based on this function will be incorrect.
  *
  *
  * @retval SYSCLK frequency
  */
//函数功能:读取系统时钟频率为170MHz

uint32_t HAL_RCC_GetSysClockFreq(void)
{
  uint32_t pllvco, pllsource, pllr, pllm;
  uint32_t sysclockfreq;

  if (__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI)
  {
    /* HSI used as system clock source */
    sysclockfreq = HSI_VALUE;
  }
  else if (__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSE)
  {
    /* HSE used as system clock source */
    sysclockfreq = HSE_VALUE;
  }
  else if (__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL)
  {//读取RCC->CFGR寄存器的bit3:2(SWS[1:0])
   //SWS[1:0]=01b,表示HSI16作为系统时钟
   //SWS[1:0]=10b,表示HSE作为系统时钟
   //SWS[1:0]=11b,表示PLL作为系统时钟
    /* PLL used as system clock  source */

    /* PLL_VCO = ((HSE_VALUE or HSI_VALUE)/ PLLM) * PLLN
    SYSCLK = PLL_VCO / PLLR
    */

    pllsource = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC);
        //读取RCC->PLLCFGR寄存器bit1:0(PLLSRC[1:0]),PLLSRC[1:0]=11b选择HSE时钟作为PLL的输入时钟源

    pllm = (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U ;
        //读取RCC->PLLCFGR寄存器bit7:4(PLLM[3:0]),PLLM[3:0]=0001b,PLLM的值为2

    switch (pllsource)
    {
    case RCC_PLLSOURCE_HSE:  /* HSE used as PLL clock source */
      pllvco = (HSE_VALUE / pllm) * (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos);
        //HSE_VALUE = 8000000,外部晶振为8MHz
        //PLL_VCO = (HSE_VALUE / PLLM) * PLLN = (8000000/2)*85=340000000Hz=340MHz

      break;

    case RCC_PLLSOURCE_HSI:  /* HSI used as PLL clock source */
    default:
      pllvco = (HSI_VALUE / pllm) * (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos);
      break;
    }

    pllr = ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1U ) * 2U;
        //RCC_PLLCFGR寄存器bit26:25(PLLR[1:0]:),PLLR[1:0]:=00,PLLR的分频值为2

    sysclockfreq = pllvco/pllr;
        //SYSCLK = PLL_VCO / PLLR = 340000000 / 2 = 170000000Hz = 170MHz
  }
  else
  {
    sysclockfreq = 0U;
  }

  return sysclockfreq;
}

1)、若程序带FreeRTOS系统,则初始化TIM1,程序如下

/**
  * @brief  This function configures the TIM1 as a time base source.
  *         The time source is configured  to have 1ms time base with a dedicated
  *         Tick interrupt priority.
  * @note   This function is called  automatically at the beginning of program after
  *         reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig().
  * @param  TickPriority: Tick interrupt priority.
  * @retval HAL status
  */
//HAL_InitTick()供HAL_Init()调用
//函数功能:将TIM1配置为向上计数,1ms中断一次
//TickPriority=TICK_INT_PRIORITY,滴答中断优先级为TICK_INT_PRIORITY=0

HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
  RCC_ClkInitTypeDef    clkconfig;
  uint32_t              uwTimclock = 0;
  uint32_t              uwPrescalerValue = 0;
  uint32_t              pFLatency;
  HAL_StatusTypeDef     status;

  /* Enable TIM1 clock */
  __HAL_RCC_TIM1_CLK_ENABLE();

  /* Get clock configuration */
  HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);

  /* Compute TIM1 clock */
  uwTimclock = HAL_RCC_GetPCLK2Freq();
    //读取PCLK2的时钟频率,Return the PCLK2 frequency

  /* Compute the prescaler value to have TIM1 counter clock equal to 1MHz */
  uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000U) - 1U);

  /* Initialize TIM1 */
  HTIM1.Instance = TIM1;

  /* Initialize TIMx peripheral as follow:

  + Period = [(TIM1CLK/1000) - 1]. to have a (1/1000) s time base.
  + Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock.
  + ClockDivision = 0
  + Counter direction = Up
  */

  HTIM1.Init.Period = (1000000U / 1000U) - 1U;
    //定时器周期999
  HTIM1.Init.Prescaler = uwPrescalerValue;
    //设置TIM1预分频器为uwPrescalerValue
  HTIM1.Init.ClockDivision = 0;
    //设置时钟分频系数,TIM1_CR1中的CKD[9:8]=00b,tDTS=ttim_ker_ck;
    //溢出时间为(999+1)*1*170/170000000/1

  HTIM1.Init.CounterMode = TIM_COUNTERMODE_UP;

  status = HAL_TIM_Base_Init(&HTIM1);
  if (status == HAL_OK)
  {
    /* Start the TIM time Base generation in interrupt mode */
    status = HAL_TIM_Base_Start_IT(&HTIM1);
        //使能HTIM1更新中断
    if (status == HAL_OK)
    {
    /* Enable the TIM1 global Interrupt */
        HAL_NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn);

//使能TIM1产生中断
      /* Configure the SysTick IRQ priority */

      if (TickPriority < (1UL << __NVIC_PRIO_BITS))
      {//若使用“NVIC中断分组4”,STM32G4XX uses 4 Bits for the Priority Levels
                //HAL库使用中断优先级组为4
                //在“stm32g474xx.h”中定义“__NVIC_PRIO_BITS=4”
                //Interrupt and exception vectors
        /* Configure the TIM IRQ priority */

        HAL_NVIC_SetPriority(TIM1_UP_TIM16_IRQn, TickPriority, 0U);
          //设置NVIC中断分组4:4位抢占优先级,0位响应优先级
          //选择中断优先级组4,即抢占优先级为4位,取值为0~15,响应优先级组为0位,取值为0
                //这里设置TIM1中断优先级为TickPriority

        uwTickPrio = TickPriority;//记录滴答时钟的中断优先级
      }
      else
      {//若没有使用“NVIC中断分组4”,则设置status
        status = HAL_ERROR;
      }
    }
  }

 /* Return function status */
  return status;
}

2)、程序不带系统,则初始化下面的函数

__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
  HAL_StatusTypeDef  status = HAL_OK;

  if (uwTickFreq != 0U)
  {
    /* Configure the SysTick to have interrupt in 1ms time basis*/
    if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) == 0U)
    {
      /* Configure the SysTick IRQ priority */
      if (TickPriority < (1UL << __NVIC_PRIO_BITS))
      {//在“stm32g474xx.h”中定义“__NVIC_PRIO_BITS=4”
        HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
        uwTickPrio = TickPriority;
      }
      else
      {
        status = HAL_ERROR;
      }
    }
    else
    {
      status = HAL_ERROR;
    }
  }
  else
  {
    status = HAL_ERROR;
  }

  /* Return function status */
  return status;
}

uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb)
{
   return SysTick_Config(TicksNumb);
}

//在“stm32g474xx.h”中定义“__Vendor_SysTickConfig”为0
//如果“__Vendor_SysTickConfig”被定义过,且“__Vendor_SysTickConfig=0”,则参与编译
#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)

/**
  \brief   System Tick Configuration
  \details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
           Counter is in free running mode to generate periodic interrupts.
  \param [in]  ticks  Number of ticks between two interrupts.
  \return          0  Function succeeded.
  \return          1  Function failed.
  \note    When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the
           function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b>
           must contain a vendor-specific implementation of this function.
 */

__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
  if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
  {
    return (1UL);                                                   /* Reload value impossible */
  }

  SysTick->LOAD  = (uint32_t)(ticks - 1UL);
    //设置计数ticks个输入时钟,则中断一次    
    //set reload register

  NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL);
    //在“stm32g474xx.h”中定义“__NVIC_PRIO_BITS=4”,这里设置SysTick中断优先级为15
    //设置NVIC中断分组4:4位抢占优先级,0位响应优先级
    //选择中断优先级组4,即抢占优先级为4位,取值为0~15,响应优先级组为0位,取值为0
    //set Priority for Systick Interrupt

  SysTick->VAL   = 0UL;
    //设置计数器值为0,Load the SysTick Counter Value
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                   SysTick_CTRL_TICKINT_Msk   |
                   SysTick_CTRL_ENABLE_Msk;
    //SysTick_CTRL_CLKSOURCE_Msk表示设置STK_CTRL寄存器bit2(CLKSOURCE),CLKSOURCE=1使用AHB时钟
    //SysTick_CTRL_TICKINT_Msk表示开启SYSTICK中断
    //SysTick_CTRL_ENABLE_Msk表示使能SysTick计数
    //Enable SysTick IRQ and SysTick Timer

  return (0UL);                                                     /* Function successful */
}

//函数功能:更新SystemCoreClock的值
void SystemCoreClockUpdate(void)
{
  uint32_t tmp, pllvco, pllr, pllsource, pllm;

  /* Get SYSCLK source -------------------------------------------------------*/
  switch (RCC->CFGR & RCC_CFGR_SWS)
  {//读取RCC->CFGR寄存器的bit3:2(SWS[1:0])
   //SWS[1:0]=01b,表示HSI16作为系统时钟
   //SWS[1:0]=10b,表示HSE作为系统时钟
   //SWS[1:0]=11b,表示PLL作为系统时钟,RCC_CFGR_SWS_PLL

    case 0x04:  /* HSI used as system clock source */
      SystemCoreClock = HSI_VALUE;
      break;

    case 0x08:  /* HSE used as system clock source */
      SystemCoreClock = HSE_VALUE;
      break;

    case 0x0C:  /* PLL used as system clock  source */
      /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLLM) * PLLN
         SYSCLK = PLL_VCO / PLLR
         */

      pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC);
          //读取RCC->PLLCFGR寄存器bit1:0(PLLSRC[1:0]),PLLSRC[1:0]=11b选择HSE时钟作为PLL的输入时钟源

      pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> 4) + 1U ;
          //读取RCC->PLLCFGR寄存器bit7:4(PLLM[3:0]),PLLM[3:0]=0001b,PLLM的值为2

      if (pllsource == 0x02UL) /* HSI used as PLL clock source */
      {
        pllvco = (HSI_VALUE / pllm);
      }
      else                   /* HSE used as PLL clock source */
      {
        pllvco = (HSE_VALUE / pllm);
                //pllvco=8000000/2=4000000
      }

      pllvco = pllvco * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 8);
        //HSE_VALUE = 8000000,外部晶振为8MHz
        //PLL_VCO = (HSE_VALUE / PLLM) * PLLN = (8000000/2)*85=340000000Hz=340MHz

      pllr = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 25) + 1U) * 2U;
            //RCC_PLLCFGR寄存器bit26:25(PLLR[1:0]:),PLLR[1:0]:=00b,PLLR的分频值为2

      SystemCoreClock = pllvco/pllr;
            //SYSCLK = PLL_VCO / PLLR = 340000000 / 2 = 170000000Hz = 170MHz
      break;

    default:
      break;
  }

  /*--- 计算HCLK时钟频率,Compute HCLK clock frequency ---*/
  tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
    //读取RCC->CFGR寄存器bit7:4(HPRE[3:0]),令HPRE[3:0]=0xxxb,AHB分频器值为1
    //Get HCLK prescaler

  SystemCoreClock >>= tmp;
    //HCLK clock frequency:更新SystemCoreClock=170MHz
}

const char fHCLK_REG[]="fHCLK=";
const char fPCLK1_REG[]="fPCLK1=";
const char fPCLK2_REG[]="fPCLK2=";
const char MHz_REG[]="MHz\r\n";
void Print_HCLK_PCLK1_PCLK2(void)
{
    uint32_t fHCLK,fPCLK1,fPCLK2;

    fHCLK=HAL_RCC_GetHCLKFreq();//读取HCLK的时钟频率
    fPCLK1=HAL_RCC_GetPCLK1Freq();//读取PCLK1的时钟频率
    fPCLK2=HAL_RCC_GetPCLK2Freq();//读取PCLK2的时钟频率

    fHCLK=fHCLK/1000000;//单位为MHz
    fPCLK1=fPCLK1/1000000;//单位为MHz
    fPCLK2=fPCLK2/1000000;//单位为MHz

    printf("%s",fHCLK_REG);
    printf("%u",fHCLK );
    printf("%s",MHz_REG );

    printf("%s",fPCLK1_REG);
    printf("%u",fPCLK1 );
    printf("%s",MHz_REG );

    printf("%s",fPCLK2_REG);
    printf("%u",fPCLK2 );
    printf("%s",MHz_REG );
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值