STM32獲取系統時鐘源和系統時鐘分配情況
阿新 • • 發佈:2021-01-21
技術標籤:MCU
STM32獲取系統時鐘源和系統時鐘分配情況
一、相關庫函式
stm32f10x_rcc.c
/**
* @brief Returns the clock source used as system clock.
* @param None
* @retval The clock source used as system clock. The returned value can
* be one of the following:
* - 0x00: HSI used as system clock
* - 0x04: HSE used as system clock
* - 0x08: PLL used as system clock
*/
uint8_t RCC_GetSYSCLKSource(void)
{
return ((uint8_t)(RCC->CFGR & CFGR_SWS_Mask));
}
stm32f10x_rcc.c
typedef struct
{
uint32_t SYSCLK_Frequency; /*!< returns SYSCLK clock frequency expressed in Hz */
uint32_t HCLK_Frequency; /*!< returns HCLK clock frequency expressed in Hz */
uint32_t PCLK1_Frequency; /*!< returns PCLK1 clock frequency expressed in Hz */
uint32_t PCLK2_Frequency; /*!< returns PCLK2 clock frequency expressed in Hz */
uint32_t ADCCLK_Frequency; /*!< returns ADCCLK clock frequency expressed in Hz */
}RCC_ClocksTypeDef;
/**
* @brief Returns the frequencies of different on chip clocks.
* @param RCC_Clocks: pointer to a RCC_ClocksTypeDef structure which will hold
* the clocks frequencies.
* @note The result of this function could be not correct when using
* fractional value for HSE crystal.
* @retval None
*/
void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks)
{
uint32_t tmp = 0, pllmull = 0, pllsource = 0, presc = 0;
#ifdef STM32F10X_CL
uint32_t prediv1source = 0, prediv1factor = 0, prediv2factor = 0, pll2mull = 0;
#endif /* STM32F10X_CL */
#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)
uint32_t prediv1factor = 0;
#endif
/* Get SYSCLK source -------------------------------------------------------*/
tmp = RCC->CFGR & CFGR_SWS_Mask;
switch (tmp)
{
case 0x00: /* HSI used as system clock */
RCC_Clocks->SYSCLK_Frequency = HSI_VALUE;
break;
case 0x04: /* HSE used as system clock */
RCC_Clocks->SYSCLK_Frequency = HSE_VALUE;
break;
case 0x08: /* PLL used as system clock */
/* Get PLL clock source and multiplication factor ----------------------*/
pllmull = RCC->CFGR & CFGR_PLLMull_Mask;
pllsource = RCC->CFGR & CFGR_PLLSRC_Mask;
#ifndef STM32F10X_CL
pllmull = ( pllmull >> 18) + 2;
if (pllsource == 0x00)
{/* HSI oscillator clock divided by 2 selected as PLL clock entry */
RCC_Clocks->SYSCLK_Frequency = (HSI_VALUE >> 1) * pllmull;
}
else
{
#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)
prediv1factor = (RCC->CFGR2 & CFGR2_PREDIV1) + 1;
/* HSE oscillator clock selected as PREDIV1 clock entry */
RCC_Clocks->SYSCLK_Frequency = (HSE_VALUE / prediv1factor) * pllmull;
#else
/* HSE selected as PLL clock entry */
if ((RCC->CFGR & CFGR_PLLXTPRE_Mask) != (uint32_t)RESET)
{/* HSE oscillator clock divided by 2 */
RCC_Clocks->SYSCLK_Frequency = (HSE_VALUE >> 1) * pllmull;
}
else
{
RCC_Clocks->SYSCLK_Frequency = HSE_VALUE * pllmull;
}
#endif
}
#else
pllmull = pllmull >> 18;
if (pllmull != 0x0D)
{
pllmull += 2;
}
else
{ /* PLL multiplication factor = PLL input clock * 6.5 */
pllmull = 13 / 2;
}
if (pllsource == 0x00)
{/* HSI oscillator clock divided by 2 selected as PLL clock entry */
RCC_Clocks->SYSCLK_Frequency = (HSI_VALUE >> 1) * pllmull;
}
else
{/* PREDIV1 selected as PLL clock entry */
/* Get PREDIV1 clock source and division factor */
prediv1source = RCC->CFGR2 & CFGR2_PREDIV1SRC;
prediv1factor = (RCC->CFGR2 & CFGR2_PREDIV1) + 1;
if (prediv1source == 0)
{ /* HSE oscillator clock selected as PREDIV1 clock entry */
RCC_Clocks->SYSCLK_Frequency = (HSE_VALUE / prediv1factor) * pllmull;
}
else
{/* PLL2 clock selected as PREDIV1 clock entry */
/* Get PREDIV2 division factor and PLL2 multiplication factor */
prediv2factor = ((RCC->CFGR2 & CFGR2_PREDIV2) >> 4) + 1;
pll2mull = ((RCC->CFGR2 & CFGR2_PLL2MUL) >> 8 ) + 2;
RCC_Clocks->SYSCLK_Frequency = (((HSE_VALUE / prediv2factor) * pll2mull) / prediv1factor) * pllmull;
}
}
#endif /* STM32F10X_CL */
break;
default:
RCC_Clocks->SYSCLK_Frequency = HSI_VALUE;
break;
}
/* Compute HCLK, PCLK1, PCLK2 and ADCCLK clocks frequencies ----------------*/
/* Get HCLK prescaler */
tmp = RCC->CFGR & CFGR_HPRE_Set_Mask;
tmp = tmp >> 4;
presc = APBAHBPrescTable[tmp];
/* HCLK clock frequency */
RCC_Clocks->HCLK_Frequency = RCC_Clocks->SYSCLK_Frequency >> presc;
/* Get PCLK1 prescaler */
tmp = RCC->CFGR & CFGR_PPRE1_Set_Mask;
tmp = tmp >> 8;
presc = APBAHBPrescTable[tmp];
/* PCLK1 clock frequency */
RCC_Clocks->PCLK1_Frequency = RCC_Clocks->HCLK_Frequency >> presc;
/* Get PCLK2 prescaler */
tmp = RCC->CFGR & CFGR_PPRE2_Set_Mask;
tmp = tmp >> 11;
presc = APBAHBPrescTable[tmp];
/* PCLK2 clock frequency */
RCC_Clocks->PCLK2_Frequency = RCC_Clocks->HCLK_Frequency >> presc;
/* Get ADCCLK prescaler */
tmp = RCC->CFGR & CFGR_ADCPRE_Set_Mask;
tmp = tmp >> 14;
presc = ADCPrescTable[tmp];
/* ADCCLK clock frequency */
RCC_Clocks->ADCCLK_Frequency = RCC_Clocks->PCLK2_Frequency / presc;
}
二、程式碼參考
typedef struct
{
u8 sys_clk_src; //檢視系統時鐘使用的時鐘源:0x00:HSI 0x04:HSE 0x08:PLL
RCC_ClocksTypeDef RCC_Clocks; //存放系統時鐘分配資訊
}sys_clk_info_stu_t;
/******************************************************************************
* @Function: get_sys_clk_info
* @Description: 獲取當前系統的時鐘資訊
* @Input: sys_clk_info:存放時鐘分配資訊的結構體地址
* @Output: None
* @Return: void
* @Others: None
* @param {sys_clk_info_stu_t} *sys_clk_info
*******************************************************************************/
void get_sys_clk_info(sys_clk_info_stu_t *sys_clk_info)
{
sys_clk_info->sys_clk_src = RCC_GetSYSCLKSource();
RCC_GetClocksFreq(&(sys_clk_info->RCC_Clocks));
}
三、效果展示
說明:從結果可以知道系統的時鐘源來源於PLL,系統時鐘頻率為72M,AHB匯流排時鐘為72M,APB1匯流排時鐘為36M,APB2匯流排時鐘為72M,ADC時鐘為36M。