STM32学习笔记(五)RCC(Reset and Clock Control)

时钟

时钟树

外部时钟

外部时钟更为精确

高速外部时钟信号 --- HSE(High-Speed External Clock Signal)
  • 复用端口:OSC_OUT 和 OSC_IN
    管脚信息可在 数据手册 中查看
    OSC_OUT 和 OSC_IN 对应管脚
  • 频率:4~16 MHz(一般连接 8MHz 晶振)
低速外部时钟信号# --- LSE(Low-Speed External Clock Signal)
  • 复用端口:OSC32_OUT 和 OSC32_IN
    管脚信息可在 数据手册 中查看
    OSC32_OUT 和 OSC32_IN 对应管脚
  • 频率:32.768 kHz(只能连接 32.768kHz 晶振)

内部时钟

高速内部时钟信号 --- HSI(High-Speed Internal Clock Signal)
  • 频率:8 MHz(由内部 RC振荡器 产生)
低速内部时钟信号 --- LSI(Low-Speed Internal Clock Signal)
  • 频率:40 kHz 左右(由内部 RC振荡器 产生)
LSI振荡器频率特性 (数据手册---电气特性)

锁相环时钟 --- PLLCLK(Phase Locked Loop Clock)

时钟树放大图中的PLLCLK
  • 产生:由图中可以看出,PLLCLK有两种来源—— HSI 和 HSE,经过倍频(PLLMUL)后输出。
  • 频率:在默认情况下,输入时钟为 HSE = 8MHz ,倍频因子为 x9,系统时钟选择 PLLCLK 达到最大频率 72MHz。如果使用内部时钟,输入时钟为 HSI / 2 = 4MHz,倍频因子最大为 x16,最高只能输出 64MHz时钟。
  • 注意
    • PLL的设置(选择HIS振荡器除2或HSE振荡器为PLL的输入时钟,和选择倍频因子)必须在其被激活前完成。一旦PLL被激活,这些参数就不能被改动(自行配置时钟时一定要先设置再激活!)。
    • 如果需要在应用中使用USB接口,PLL必须被设置为输出48或72MHZ时钟,用于提供48MHz的USBCLK时钟。

RCC寄存器

  • 时钟控制寄存器 --- CR(Clock control register):使能 和 调整 HSI、HSE、PLL 时钟;

    • 作用---使能:位0为 HSI 使能;位16为 HSE 使能;位24为 PLL 使能;
    • 作用---时钟就绪标志:位1为 HSI 就绪;位17为 HSE 就绪;位25为 PLL 就绪;
    • 复位值:0x000 XX83
  • 时钟配置寄存器 --- CFGR(Clock configuration register):配置 分频和倍频、系统时钟和PLL时钟选择、时钟外部输出(至示波器等);

    • 作用---选择系统时钟:位1:0,00为HSI,01为HSE,10为PLL;
    • 作用---选择 PLL 时钟( HSE 或 HSI / 2 或 HSE / 2);
    • 作用---(预)分频和倍频,并设置分频因子和倍频因子;
    • 作用---输出时钟至IO口(IO口最高频率为50MHz,即输出时钟频率最大为50MHz);(其实高于50MHz也可以,但是会失真)
    • 复位值:0x0000 0000
  • 时钟中断寄存器 --- CIR(Clock interrupt register):使能时钟就绪的中断,清楚时钟就绪标志位;

    • 作用---使能时钟就绪的中断:时钟准备就绪,标志位置位,如果使能了该中断则会产生一个中断;
    • 作用---清除(复位)时钟准备就绪后产生的标志位;
    • 作用---判断 HSE 是否故障,若失效则 位7"CSCC" 置1;
    • 复位值:0x0000 0000
  • APB2外设复位寄存器 --- APB2RSTR(APB2 peripheral reset register):将APB2总线上的外设恢复至复位值;

    • 复位值:0x0000 0000
  • APB1外设复位寄存器 --- APB1RSTR(APB1 peripheral reset register):将APB1总线上的外设恢复至复位值;

    • 复位值:0x0000 0000
  • AHB外设时钟使能寄存器 --- AHBENR(AHB peripheral clock enable register):使能AHB总线上的外设;

    • 复位值:0x0000 0014
    • 注意:该寄存器只有DMA1、DMA2、SRAM、FLITF、CRC(循环冗余校验)、FSMC(可变静态存储控制器)、SDIO的时钟使能,其中DMA1、DMA2、SRAM、FLITF的时钟默认已经被使能;
  • APB2外设时钟使能寄存器 --- APB2ENR(APB2 peripheral clock enable register):使能APB2总线上的外设;

    • 复位值:0x0000 0000
    • 注意:除 EXTI(外部中断)外所有挂载在 APB2总线 上的外设均能通过该寄存器使能;
  • APB1外设时钟使能寄存器 --- APB1ENR(APB1 peripheral clock enable register):使能APB1总线上的外设;

    • 复位值:0x0000 0000
    • 注意:除 RTC(Real-Time Clock)(实时时钟)外所有挂载在 APB1总线上的外设均可通过该寄存器使能;
  • 备份域控制寄存器 --- BDCR(Backup domain control register):RTC(Real-Time Clock)(实时时钟)的使能和配置,LSE 的使能和配置;

    • 复位值:0x0000 0000
    • 注意:RTC是一个掉电后还继续运行的定时器
  • 控制/状态寄存器 --- CSR(Control/status register):储存/消除 复位标志,LSI 的就绪标志位;

    • 复位值:0x0000 0000

常用RCC固件库函数 (stm32f10x_rcc.h)

固件库中 HSE默认为 8M, 默认使用 HSE 9倍频 的 PLL时钟 作为系统时钟,若要更改时钟配置,推荐使用固件库函数更改而非直接更改固件库

AHB上外设使能函数 --- RCC_AHBPeriphClockCmd

void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);
  • RCC_AHBPeriph:对应外设;
  • NewState:ENABLE 为使能,DISABLE 为关闭;
  • 示例:
//使能 FMSC
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE)

APB2高速总线上外设使能函数 --- RCC_APB2PeriphClockCmd

void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
  • RCC_APB2Periph:对应外设;
  • NewState:ENABLE 为使能,DISABLE 为关闭;
  • 示例:
//使能 GPIOA口
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE)

APB1低速总线上外设使能函数 --- RCC_APB1PeriphClockCmd

void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
  • RCC_APB1Periph:对应外设;
  • NewState:ENABLE 为使能,DISABLE 为关闭;
  • 示例:
//使能 USART2
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

RCC清理函数 --- RCC_DeInit

void RCC_DeInit(void);
  • 作用:只打开 HSI 时钟,其余所有时钟包括系统时钟均关闭,清楚所有时钟就绪中断标志位,关闭时钟对外输出;
  • 示例:
RCC_DeInit();

HSE时钟使能函数 --- RCC_HSEConfig

void RCC_HSEConfig(uint32_t RCC_HSE);
  • RCC_HSE:可以为 OFF,ON,Bypass;
  • 作用:参数 RCC_HSE 为 RCC_HSE_OFF 时关闭 HSE 时钟,为 RCC_HSE_ON 时打开 HSE 时钟,为RCC_HSE_Bypass 时打开 HSE 时钟的同时还打开 时钟安全系统(CSS) 的时钟;
  • 注明:时钟安全系统(CSS) 开启后,如果HSE时钟发生故障,HSE振荡器被自动关闭,时钟失效事件将被送到高级定时器(TIM1和TIM8)的刹车输入端,并产生时钟安全中断CSSI,此CSSI中断连接到Cortex™-M3的NMI中断;
  • 示例:
//使能HSE
RCC_HSEConfig(RCC_HSE_ON);

HSE判断时钟启动就绪函数--- RCC_WaitForHSEStartUp

typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrorStatus;
ErrorStatus RCC_WaitForHSEStartUp(void);
  • 返回值:SUCCESS 表示启动成功, ERROR 表示启动失败;
  • 示例:
ErrorStatus HSEStatus;
HSEStatus = RCC_WaitForHSEStartUp();
//等待 HSE 就绪
if(HSEStatus == SUCCESS)
{
  // HSE 就绪后实现后需要运行的程序
}

HSI时钟使能函数 --- RCC_HSICmd

typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;
void RCC_HSICmd(FunctionalState NewState);
  • NewState:可以为 ENABLE,DISABLE;
  • 示例:
//使能HSI
RCC_HSICmd(ENABLE);

PLL时钟配置函数 --- RCC_PLLConfig

void RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul);
  • RCC_PLLSource:PLL的时钟源,可选择 HSI二分频(RCC_PLLSource_HSI_Div2)、HSE(RCC_PLLSource_HSE_Div1)、HSE二分频(RCC_PLLSource_HSE_Div2);
  • RCC_PLLMul_x:倍频因子,互联型 x 可为 (2~9),其他则可为 (2~16);
  • 示例:
//配置锁相环时钟 PLLCLK = HSE * 9
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

PLL时钟使能函数 --- RCC_PLLCmd

void RCC_PLLCmd(FunctionalState NewState);
  • NewState:可以为 ENABLE,DISABLE;
  • 注意:必须先配置PLL,再使能;
  • 示例:
//使能 PLL
RCC_PLLCmd(ENABLE);

系统时钟配置函数 --- RCC_SYSCLKConfig

void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource);
  • RCC_SYSCLKSource:系统的时钟源,可选择 HSI(RCC_SYSCLKSource_HSI)、HSE(RCC_SYSCLKSource_HSE)、PLL(RCC_SYSCLKSource_PLLCLK);
  • 示例:
//选择系统时钟 为PLL时钟
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

自行配置系统时钟

程序思路

  • RCC清除,便于自行配置;
  • 使能 HSE 或 HSI(系统时钟为高速时钟);
  • 等待使能完成;
  • 使能FLASH预取缓冲器,并设置为2个等待周期
  • 设置 AHB、APB1、APB2的预分频因子;
  • 配置锁相环时钟:选择锁相环时钟源和倍频因子;
  • 使能锁相环时钟(再次强调要先配置锁相环再使能);
  • 等待PLL时钟稳定;
  • 选择系统时钟为PLL时钟;
  • 等待系统时钟稳定;
    (若不选择PLL为系统时钟,且不需USB,可不开启PLL)

以下程序为复制粘贴火哥源码。

HSE作为系统时钟

// 默认 HSE 晶振频率为 8M
void HSE_SetSysClk(uint32_t RCC_PLLMul_x)               //时钟为8M*x
{
    ErrorStatus HSEStatus;
    
    //RCC寄存器复位
    RCC_DeInit();
    
    //使能HSE
    RCC_HSEConfig(RCC_HSE_ON);
    
    //等待HSE就绪
    HSEStatus = RCC_WaitForHSEStartUp();
    if(HSEStatus == SUCCESS)
    {
        //使能预取缓冲器(预取指)
        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
        //配置两个等待周期
        FLASH_SetLatency(FLASH_Latency_2);
        
        //设置分频因子
        RCC_HCLKConfig(RCC_SYSCLK_Div1);
        RCC_PCLK1Config(RCC_HCLK_Div2);
        RCC_PCLK2Config(RCC_HCLK_Div1);
        
        //配置锁相环时钟 PLLCLK = HSE * RCC_PLLMul_x
        RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_x);
        //使能PLL
        RCC_PLLCmd(ENABLE);
        //等待PLL时钟稳定
        while( RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET );
        
        //选择系统时钟 为PLL时钟
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
        
        while( RCC_GetSYSCLKSource() != 0x08 );
    }
    else
    {
        // 故障后处理程序
    }
}

HSI作为系统时钟

void HSI_SetSysClk(uint32_t RCC_PLLMul_x)               //时钟为4M*x
{
    __IO uint32_t HSIStatus = 0;
    
    //RCC寄存器复位
    RCC_DeInit();
    
    //使能HSI
    RCC_HSICmd(ENABLE);
    
    //等待HSI就绪
    HSIStatus = RCC->CR & RCC_CR_HSIRDY;
    if(HSIStatus == RCC_CR_HSIRDY)
    {
        //使能预取缓冲器(预取指)
        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
        //配置两个等待周期
        FLASH_SetLatency(FLASH_Latency_2);
        
        //设置分频因子
        RCC_HCLKConfig(RCC_SYSCLK_Div1);
        RCC_PCLK1Config(RCC_HCLK_Div2);
        RCC_PCLK2Config(RCC_HCLK_Div1);
        
        //配置锁相环时钟 PLLCLK = HSE * RCC_PLLMul_x
        RCC_PLLConfig(RCC_PLLSource_HSI_Div2,RCC_PLLMul_x);
        //使能PLL
        RCC_PLLCmd(ENABLE);
        //等待PLL时钟稳定
        while( RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET );
        
        //选择系统时钟 为PLL时钟
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
        
        while( RCC_GetSYSCLKSource() != 0x08 );
    }
    else
    {
        // 故障后处理程序
    }
}

你可能感兴趣的:(STM32学习笔记(五)RCC(Reset and Clock Control))