📄 stm32l1xx_rcc.c
字号:
prescaler and used to clock the CPU, memory and peripherals mapped
on AHB bus (DMA and GPIO).APB1 (PCLK1) and APB2 (PCLK2) clocks are
derived from AHB clock through configurable prescalers and used to
clock the peripherals mapped on these busses. You can use
"RCC_GetClocksFreq()" function to retrieve the frequencies of these
clocks.
-@- All the peripheral clocks are derived from the System clock (SYSCLK)
except:
(+@) The USB 48 MHz clock which is derived from the PLL VCO clock.
(+@) The ADC clock which is always the HSI clock. A divider by 1, 2
or 4 allows to adapt the clock frequency to the device operating
conditions.
(+@) The RTC/LCD clock which is derived from the LSE, LSI or 1 MHz
HSE_RTC (HSE divided by a programmable prescaler).
The System clock (SYSCLK) frequency must be higher or equal to
the RTC/LCD clock frequency.
(+@) IWDG clock which is always the LSI clock.
(#) The maximum frequency of the SYSCLK, HCLK, PCLK1 and PCLK2 is 32 MHz.
Depending on the device voltage range, the maximum frequency should
be adapted accordingly:
+----------------------------------------------------------------+
| Wait states | HCLK clock frequency (MHz) |
| |------------------------------------------------|
| (Latency) | voltage range | voltage range |
| | 1.65 V - 3.6 V | 2.0 V - 3.6 V |
| |----------------|---------------|---------------|
| | VCORE = 1.2 V | VCORE = 1.5 V | VCORE = 1.8 V |
|-------------- |----------------|---------------|---------------|
|0WS(1CPU cycle)|0 < HCLK <= 2 |0 < HCLK <= 8 |0 < HCLK <= 16 |
|---------------|----------------|---------------|---------------|
|1WS(2CPU cycle)|2 < HCLK <= 4 |8 < HCLK <= 16 |16 < HCLK <= 32|
+----------------------------------------------------------------+
(#) After reset, the System clock source is the MSI (2 MHz) with 0 WS,
Flash 32-bit access is enabled and prefetch is disabled.
[..] It is recommended to use the following software sequences to tune the
number of wait states needed to access the Flash memory with the CPU
frequency (HCLK).
(+) Increasing the CPU frequency (in the same voltage range)
(+) Program the Flash 64-bit access, using "FLASH_ReadAccess64Cmd(ENABLE)"
function
(+) Check that 64-bit access is taken into account by reading FLASH_ACR
(+) Program Flash WS to 1, using "FLASH_SetLatency(FLASH_Latency_1)"
function
(+) Check that the new number of WS is taken into account by reading
FLASH_ACR
(+) Modify the CPU clock source, using "RCC_SYSCLKConfig()" function
(+) If needed, modify the CPU clock prescaler by using "RCC_HCLKConfig()"
function
(+) Check that the new CPU clock source is taken into account by reading
the clock source status, using "RCC_GetSYSCLKSource()" function
(+) Decreasing the CPU frequency (in the same voltage range)
(+) Modify the CPU clock source, using "RCC_SYSCLKConfig()" function
(+) If needed, modify the CPU clock prescaler by using "RCC_HCLKConfig()"
function
(+) Check that the new CPU clock source is taken into account by reading
the clock source status, using "RCC_GetSYSCLKSource()" function
(+) Program the new number of WS, using "FLASH_SetLatency()" function
(+) Check that the new number of WS is taken into account by reading
FLASH_ACR
(+) Enable the Flash 32-bit access, using "FLASH_ReadAccess64Cmd(DISABLE)"
function
(+) Check that 32-bit access is taken into account by reading FLASH_ACR
@endverbatim
* @{
*/
/**
* @brief Configures the system clock (SYSCLK).
* @note The MSI is used (enabled by hardware) as system clock source after
* startup from Reset, wake-up from STOP and STANDBY mode, 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 will be ready.
* You can use RCC_GetSYSCLKSource() function to know which clock is
* currently used as system clock source.
* @param RCC_SYSCLKSource: specifies the clock source used as system clock source
* This parameter can be one of the following values:
* @arg RCC_SYSCLKSource_MSI: MSI selected as system clock source
* @arg RCC_SYSCLKSource_HSI: HSI selected as system clock source
* @arg RCC_SYSCLKSource_HSE: HSE selected as system clock source
* @arg RCC_SYSCLKSource_PLLCLK: PLL selected as system clock source
* @retval None
*/
void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_RCC_SYSCLK_SOURCE(RCC_SYSCLKSource));
tmpreg = RCC->CFGR;
/* Clear SW[1:0] bits */
tmpreg &= ~RCC_CFGR_SW;
/* Set SW[1:0] bits according to RCC_SYSCLKSource value */
tmpreg |= RCC_SYSCLKSource;
/* Store the new value */
RCC->CFGR = tmpreg;
}
/**
* @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 values:
* - 0x00: MSI used as system clock
* - 0x04: HSI used as system clock
* - 0x08: HSE used as system clock
* - 0x0C: PLL used as system clock
*/
uint8_t RCC_GetSYSCLKSource(void)
{
return ((uint8_t)(RCC->CFGR & RCC_CFGR_SWS));
}
/**
* @brief Configures the AHB clock (HCLK).
* @note Depending on the device voltage range, the software has to set correctly
* these bits to ensure that the system frequency does not exceed the
* maximum allowed frequency (for more details refer to section above
* "CPU, AHB and APB busses clocks configuration functions")
* @param RCC_SYSCLK: defines the AHB clock divider. This clock is derived from
* the system clock (SYSCLK).
* This parameter can be one of the following values:
* @arg RCC_SYSCLK_Div1: AHB clock = SYSCLK
* @arg RCC_SYSCLK_Div2: AHB clock = SYSCLK/2
* @arg RCC_SYSCLK_Div4: AHB clock = SYSCLK/4
* @arg RCC_SYSCLK_Div8: AHB clock = SYSCLK/8
* @arg RCC_SYSCLK_Div16: AHB clock = SYSCLK/16
* @arg RCC_SYSCLK_Div64: AHB clock = SYSCLK/64
* @arg RCC_SYSCLK_Div128: AHB clock = SYSCLK/128
* @arg RCC_SYSCLK_Div256: AHB clock = SYSCLK/256
* @arg RCC_SYSCLK_Div512: AHB clock = SYSCLK/512
* @retval None
*/
void RCC_HCLKConfig(uint32_t RCC_SYSCLK)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_RCC_HCLK(RCC_SYSCLK));
tmpreg = RCC->CFGR;
/* Clear HPRE[3:0] bits */
tmpreg &= ~RCC_CFGR_HPRE;
/* Set HPRE[3:0] bits according to RCC_SYSCLK value */
tmpreg |= RCC_SYSCLK;
/* Store the new value */
RCC->CFGR = tmpreg;
}
/**
* @brief Configures the Low Speed APB clock (PCLK1).
* @param RCC_HCLK: defines the APB1 clock divider. This clock is derived from
* the AHB clock (HCLK).
* This parameter can be one of the following values:
* @arg RCC_HCLK_Div1: APB1 clock = HCLK
* @arg RCC_HCLK_Div2: APB1 clock = HCLK/2
* @arg RCC_HCLK_Div4: APB1 clock = HCLK/4
* @arg RCC_HCLK_Div8: APB1 clock = HCLK/8
* @arg RCC_HCLK_Div16: APB1 clock = HCLK/16
* @retval None
*/
void RCC_PCLK1Config(uint32_t RCC_HCLK)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_RCC_PCLK(RCC_HCLK));
tmpreg = RCC->CFGR;
/* Clear PPRE1[2:0] bits */
tmpreg &= ~RCC_CFGR_PPRE1;
/* Set PPRE1[2:0] bits according to RCC_HCLK value */
tmpreg |= RCC_HCLK;
/* Store the new value */
RCC->CFGR = tmpreg;
}
/**
* @brief Configures the High Speed APB clock (PCLK2).
* @param RCC_HCLK: defines the APB2 clock divider. This clock is derived from
* the AHB clock (HCLK).
* This parameter can be one of the following values:
* @arg RCC_HCLK_Div1: APB2 clock = HCLK
* @arg RCC_HCLK_Div2: APB2 clock = HCLK/2
* @arg RCC_HCLK_Div4: APB2 clock = HCLK/4
* @arg RCC_HCLK_Div8: APB2 clock = HCLK/8
* @arg RCC_HCLK_Div16: APB2 clock = HCLK/16
* @retval None
*/
void RCC_PCLK2Config(uint32_t RCC_HCLK)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_RCC_PCLK(RCC_HCLK));
tmpreg = RCC->CFGR;
/* Clear PPRE2[2:0] bits */
tmpreg &= ~RCC_CFGR_PPRE2;
/* Set PPRE2[2:0] bits according to RCC_HCLK value */
tmpreg |= RCC_HCLK << 3;
/* Store the new value */
RCC->CFGR = tmpreg;
}
/**
* @brief Returns the frequencies of the System, AHB and APB busses clocks.
* @note The frequency returned by this function is not the real frequency
* in the chip. It is calculated based on the predefined constant and
* the source selected by RCC_SYSCLKConfig():
*
* @note If SYSCLK source is MSI, function returns values based on MSI
* Value as defined by the MSI range, refer to RCC_MSIRangeConfig()
*
* @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(**)
* or HSI_VALUE(*) multiplied/divided by the PLL factors.
*
* (*) HSI_VALUE is a constant defined in stm32l1xx.h file (default value
* 16 MHz) but the real value may vary depending on the variations
* in voltage and temperature, refer to RCC_AdjustHSICalibrationValue().
*
* (**) HSE_VALUE is a constant defined in stm32l1xx.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
* return wrong result.
*
* - The result of this function could be not correct when using fractional
* value for HSE crystal.
*
* @param RCC_Clocks: pointer to a RCC_ClocksTypeDef structure which will hold
* the clocks frequencies.
*
* @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, HCLK, PCLK1 and/or PCLK2 clock changes, this function
* must be called to update the structure's field. Otherwise, any
* configuration based on this function will be incorrect.
*
* @retval None
*/
void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks)
{
uint32_t tmp = 0, pllmul = 0, plldiv = 0, pllsource = 0, presc = 0, msirange = 0;
/* Get SYSCLK source -------------------------------------------------------*/
tmp = RCC->CFGR & RCC_CFGR_SWS;
switch (tmp)
{
case 0x00: /* MSI used as system clock */
msirange = (RCC->ICSCR & RCC_ICSCR_MSIRANGE ) >> 13;
RCC_Clocks->SYSCLK_Frequency = (32768 * (1 << (msirange + 1)));
break;
case 0x04: /* HSI used as system clock */
RCC_Clocks->SYSCLK_Frequency = HSI_VALUE;
break;
case 0x08: /* HSE used as system clock */
RCC_Clocks->SYSCLK_Frequency = HSE_VALUE;
break;
case 0x0C: /* PLL used as system clock */
/* Get PLL clock source and multiplication factor ----------------------*/
pllmul = RCC->CFGR & RCC_CFGR_PLLMUL;
plldiv = RCC->CFGR & RCC_CFGR_PLLDIV;
pllmul = PLLMulTable[(pllmul >> 18)];
plldiv = (plldiv >> 22) + 1;
pllsource = RCC->CFGR & RCC_CFGR_PLLSRC;
if (pllsource == 0x00)
{
/* HSI oscillator clock selected as PLL clock source */
RCC_Clocks->SYSCLK_Frequency = (((HSI_VALUE) * pllmul) / plldiv);
}
else
{
/* HSE selected as PLL clock source */
RCC_Clocks->SYSCLK_Frequency = (((HSE_VALUE) * pllmul) / plldiv);
}
break;
default: /* MSI used as system clock */
msirange = (RCC->ICSCR & RCC_ICSCR_MSIRANGE ) >> 13;
RCC_Clocks->SYSCLK_Frequency = (32768 * (1 << (msirange + 1)));
break;
}
/* Compute HCLK, PCLK1, PCLK2 and ADCCLK clocks frequencies ----------------*/
/* Get HCLK prescaler */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -