RCC(复位和时钟控制)

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 PLLPLLI2S

  • 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时钟。

分倍频系数

序号系数名描述
1PLLQ主PLL(Main PLL) 分频系数,适应于USB OTG FS、SDIO 和随机数发生器时钟。
2PLLP主PLL(Main PLL) 分频系数,适用于主系统时钟。
3PLLN主PLL(Main PLL) 倍频系数。
4PLLM适用于主PLL(Main PLL)和音频 PLL(PLLI2S) 输入时钟的分频系数。
5PLLISRI2S时钟的 PLLI2S 分频系数

PLL时钟的计算 

  1. PLLCLK = PLLIN * PLLN / (PLLM * PLLP)
  2. PLL(USB OTG FS) = PLLIN * PLLN / (PLLM * PLLQ)
  3. PLL(I2SCLK) = PLLIN * PLLN / (PLLM * PLLSR)

 例如我们想配置系统高速时钟为168MHz,那么在保证VCO的两个限制条件

1. 输入频率介于1MHz和2MHz之间;

2. 输出频率介于192MHz和432MHz之间。

之后的配置如下:

 注意
1.分频和倍频系数是有取值范围的;
2.VCO的输入和输出频率也有推荐取值,以便限制PLL抖动。

RCC相关寄存器

CRHSI,HSE,CSS,PLL等的使能
CFGRPLL等的时钟源选择以及分频系数设定
CIR清除/使能 时钟就绪中断
APB2RSTRAPB2线上外设复位寄存器
APB1RSTRAPB1线上外设复位寄存器
AHBENRDMA,SDIO等时钟使能
APB2ENRAPB2线上外设时钟使能
APB1ENRAPB1线上外设时钟使能
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,将倍频数设置为,这样使用内部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 )
        { }

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值