RCC介绍
RCC:(Reset and Clock Control)复位和时钟控制的缩写,是STM32微控制器的时钟控制寄存器。时钟系统是嵌入式系统的核心组成部分,它为处理器内核和外设提供所需的时钟信号,确保它们能够正常工作。
RCC时钟树
RCC时钟源
HSI | 高速内部时钟,通常频率为8MHz,是上电后默认的系统时钟。 |
HSE | 高速外部时钟,可以接入石英/陶瓷谐振器或外部时钟源,频率范围为4MHz~16MHz。 |
LSI | 低速内部时钟信号,频率为40kHz,用于独立看门狗(IWDG)和实时时钟(RTC)。 |
LSE | 低速外部时钟信号,连接频率为32.768kHz的石英晶体。 |
PLL | 一个倍频器,其输入源可以选择为HSI/2、HSE或HSE/2,倍频因子可以选择为2~16倍,但输出频率最大不得超过72MHz。 |
STM32的PLL
不同系列的MCU的PLL个数不同,STM32F4xx系列有两个PLL,分别是Main PLL和PLLI2S。
- Main PLL由 HSE 或 HSI 振荡器提供时钟信号,并具有两个不同的输出时钟。
1. 输出高速系统时钟(Max:168MHz)。
2. 输出USB OTG FS的时钟(48MHz)、随机数发生器的时钟 (≤48 MHz) 和 SDIO 时钟 (≤48 MHz)。
- PLLI2S专用于生成精确时钟,从而在I2S接口实现高品质的音频性能。
基本结构
外部时钟源经PLL源选择开关后作为PLLIN输入到PLL中,经分频和倍频后分别输出到后端系统时钟选择开关、USB OTG FS时钟及I2S时钟。
分倍频系数
序号 | 系数名 | 描述 |
1 | PLLQ | 主PLL(Main PLL) 分频系数,适应于USB OTG FS、SDIO 和随机数发生器时钟。 |
2 | PLLP | 主PLL(Main PLL) 分频系数,适用于主系统时钟。 |
3 | PLLN | 主PLL(Main PLL) 倍频系数。 |
4 | PLLM | 适用于主PLL(Main PLL)和音频 PLL(PLLI2S) 输入时钟的分频系数。 |
5 | PLLISR | I2S时钟的 PLLI2S 分频系数 |
PLL时钟的计算
- PLLCLK = PLLIN * PLLN / (PLLM * PLLP)
- PLL(USB OTG FS) = PLLIN * PLLN / (PLLM * PLLQ)
- PLL(I2SCLK) = PLLIN * PLLN / (PLLM * PLLSR)
例如我们想配置系统高速时钟为168MHz,那么在保证VCO的两个限制条件
1. 输入频率介于1MHz和2MHz之间;
2. 输出频率介于192MHz和432MHz之间。
之后的配置如下:
注意
1.分频和倍频系数是有取值范围的;
2.VCO的输入和输出频率也有推荐取值,以便限制PLL抖动。
RCC相关寄存器
CR | HSI,HSE,CSS,PLL等的使能 |
CFGR | PLL等的时钟源选择以及分频系数设定 |
CIR | 清除/使能 时钟就绪中断 |
APB2RSTR | APB2线上外设复位寄存器 |
APB1RSTR | APB1线上外设复位寄存器 |
AHBENR | DMA,SDIO等时钟使能 |
APB2ENR | APB2线上外设时钟使能 |
APB1ENR | APB1线上外设时钟使能 |
BDCR | 备份域控制寄存器 |
CSR | 控制/状态寄存器 |
RCC初始化
一般用外部晶振做时钟源比较多。默认时钟设置,外部8M晶振
在 system_stm32f10x.c 文件里面, SystemInit()函数设置时钟。
代码如下:
void SystemInit (void)
{
/* Reset the RCC clock configuration to the default reset state(for debug purpose) */
/* Set HSION bit */
RCC->CR |= (uint32_t)0x00000001;
/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#ifndef STM32F10X_CL
RCC->CFGR &= (uint32_t)0xF8FF0000;
#else
RCC->CFGR &= (uint32_t)0xF0FF0000;
#endif /* STM32F10X_CL */
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= (uint32_t)0xFEF6FFFF;
/* Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF;
/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
RCC->CFGR &= (uint32_t)0xFF80FFFF;
#ifdef STM32F10X_CL
/* Reset PLL2ON and PLL3ON bits */
RCC->CR &= (uint32_t)0xEBFFFFFF;
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x00FF0000;
/* Reset CFGR2 register */
RCC->CFGR2 = 0x00000000;
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x009F0000;
/* Reset CFGR2 register */
RCC->CFGR2 = 0x00000000;
#else
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x009F0000;
#endif /* STM32F10X_CL */
#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
#ifdef DATA_IN_ExtSRAM
SystemInit_ExtMemCtl();
#endif /* DATA_IN_ExtSRAM */
#endif
/* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
/* Configure the Flash Latency cycles and enable prefetch buffer */
SetSysClock();
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif
}
如果我们使用内部RC振荡器做时钟源,需要重写SystemInit()函数。
内部RC默认为8M,将倍频数设置为9,这样使用内部RC振荡器之后,时钟频率就是36MHz。为使用外部晶振频率72MHz的一半。
/*PLLCLK=8/2*9=36MHz 设置倍频得到时钟源PLL的频率*/
RCC->CFGR |= ( uint32_t ) RCC_CFGR_PLLMULL9; //设置倍频后的频率
代码如下:
注意SetSysClock() -- SetSysClockTo72();核心函数不能注释。
/* 开启HSI 即内部晶振时钟 */
RCC->CR |= ( uint32_t ) 0x00000001;
/*选择HSI为PLL的时钟源HSI必须2分频给PLL*/
RCC->CFGR |= ( uint32_t ) RCC_CFGR_PLLSRC_HSI_Div2;
/*PLLCLK=8/2*9=36MHz 设置倍频得到时钟源PLL的频率*/
RCC->CFGR |= ( uint32_t ) RCC_CFGR_PLLMULL9;//设置倍频后的频率
/* PLL不分频输出 ?*/
RCC->CFGR |= ( uint32_t ) RCC_CFGR_HPRE_DIV1;
/* 使能 PLL时钟 */
RCC->CR |= RCC_CR_PLLON;
/* 等待PLL时钟就绪*/
while ( ( RCC->CR & RCC_CR_PLLRDY ) == 0 )
{
}
/* 选择PLL为系统时钟的时钟源 */
RCC->CFGR &= ( uint32_t ) ( ( uint32_t ) ~ ( RCC_CFGR_SW ) );
RCC->CFGR |= ( uint32_t ) RCC_CFGR_SW_PLL;
/* 等到PLL成为系统时钟的时钟源*/
while ( ( RCC->CFGR & ( uint32_t ) RCC_CFGR_SWS ) != ( uint32_t ) 0x08 )
{ }