当前位置: 首页 > article >正文

【STM32】RCC系统时钟

目录

    • 一、什么是系统时钟
    • 二、RCC系统时钟和系统时钟的关系
    • 三、RCC介绍
      • RCC的作用
      • RCC的主要时钟源
      • 相关寄存器
    • 四、RCC复位和系统复位
      • RCC复位
      • 系统复位
        • 1. 重新上电
        • 2. 硬件复位
        • 3. 独立看门狗(IWDG)复位
        • 4. 软件复位
    • 五、时钟
      • 时钟树
    • 六、配置时钟
      • 示例代码

一、什么是系统时钟

系统时钟是MCU所有外设和内核运行的时钟源,决定了CPU、总线和外设的工作频率。STM32通常支持多时钟源,并通过时钟树配置分频/倍频。

二、RCC系统时钟和系统时钟的关系

RCC系统时钟是配置层,负责时钟源管理和分配。

系统时钟-SYSCLK是执行层,直接影响CPU性能和外设时序。

(RCC)Reset and Clock Control,复位和时钟控制, 负责管理整个芯片的时钟复位

时钟系统相当于芯片的心跳, 负责整个系统的稳定动作和节奏

三、RCC介绍

RCC的作用

  1. 系统时钟配置(HSE、HSI、PLL等时钟源选择)
  2. 外设时钟管理(为 GPIO、USART、SPI、I2C、ADC 等模块提供时钟)
  3. 复位控制(对外设或整个系统进行复位)
  4. 低功耗管理(控制低功耗模式下的时钟)

RCC的主要时钟源

  • HSE(High-Speed External):外部高速晶振(通常 8MHz、25MHz)
  • HSI(High-Speed Internal):内部高速时钟(如 STM32F4 默认 16MHz)
  • LSE(Low-Speed External):外部低速晶振(通常 32.768kHz,用于 RTC)
  • LSI(Low-Speed Internal):内部低速时钟(约 32kHz)
  • PLL(Phase-Locked Loop):锁相环,用于倍频,提高主频

相关寄存器

寄存器作用
RCC_CR控制时钟源(HSI、HSE、PLL)
RCC_CFGR选择系统时钟、预分频系数
RCC_AHBENR使能 AHB 总线外设时钟
RCC_APB1ENR使能 APB1 总线外设时钟
RCC_APB2ENR使能 APB2 总线外设时钟
RCC_BDCR低功耗相关,如 LSE 控制
RCC_CSR复位标志等状态控制

四、RCC复位和系统复位

RCC复位

  • 作用范围:主要针对时钟系统(如HSE/HSI/PLL配置异常、时钟源切换失败等),属于时钟树相关的局部复位。
  • 触发条件:
    • 时钟就绪超时(如HSE启动失败)。
    • PLL解锁(PLL配置错误或失锁)。
    • 时钟安全系统(CSS)检测到外部时钟故障。
  • 影响:通常不会导致整个系统复位,但可能引发时钟中断(如CSS中断),需软件干预恢复。

系统复位

  • 作用范围:全局复位(CPU、外设、内存等全部重置)
    如:
    • 上电复位(POR)。
    • 看门狗复位(IWDG/WWDG)。
    • 软件复位(NVIC_SystemReset())。
    • 硬件引脚复位(NRST引脚低电平)。
  • 触发条件:更广泛,包含所有导致系统重启的硬件/软件事件。

对于嵌入式芯片来说, 系统复位就是指重启

重启之后, 所有寄存器会恢复初始状态(初始值查阅手册) , 软件会重新从头运行

在这里插入图片描述

1. 重新上电

开关机

2. 硬件复位

STM32有一个专门的NRST引脚, 作为复位引脚, 上电状态下, NRST拉低 (电压低于0.8V, 时间持续100ns) 会导致系统硬件复位

典型电路
在这里插入图片描述
在这里插入图片描述

3. 独立看门狗(IWDG)复位
  • STM32 内部的 独立看门狗(IWDG) 可用于系统异常时自动复位。
  • 如果开启了看门狗功能, 需要软件定期喂狗,否则 MCU 认为程序失控,自动复位
4. 软件复位

执行 NVIC_SystemReset();函数复位, 这是ARM内核提供的一个函数, 实际是控制一个中断寄存器来复位

相比硬件复位, 软件复位会重新回到main()执行, 而不是bootloader, 另外不是所有的寄存器都复位

五、时钟

时钟树

在这里插入图片描述
这个直接看懵
一张图解决
在这里插入图片描述

只有这三种时钟源可被用来驱动系统时钟(SYSCLK):
● HSI振荡器时钟
● HSE振荡器时钟
● PLL时钟

而其他时钟源(如LSI、LSE)通常不被直接用作SYSCLK,主要原因包括频率范围、稳定性、精度以及系统设计需求。

分频关系:

  • SYSCLK 最大72M

  • AHB时钟HCLK = SYSCLK / AHB预分频器, 最大72M

  • APB1时钟PCLK1 = SYSCLK / APB1预分频器, 最大36M

  • APB2时钟PCLK2 = SYSCLK / APB2预分频器, 最大72M

六、配置时钟

  • 初始状态使用HSI作为时钟源, 为8M

  • 我们使用的工程使用的是ARM提供的默认初始代码, 将其设置为72M(HSE+PLL)

  • 设置和调整时钟使用RCC相关函数, 调整RCC相关寄存器

  • RCC库中重要的标准库函数

    函数作用
    RCC_DeInit将外设 RCC 寄存器重设为缺省值
    RCC_HSEConfig设置外部高速晶振(HSE)
    RCC_WaitForHSEStartUp等待 HSE 起振
    RCC_HSICmd使能或者失能内部高速晶振(HSI)
    RCC_PLLConfig设置 PLL 时钟源及倍频系数
    RCC_PLLCmd使能或者失能 PLL
    RCC_SYSCLKConfig设置系统时钟(SYSCLK)
    RCC_HCLKConfig设置 AHB 时钟(HCLK)
    RCC_PCLK1Config设置低速 AHB 时钟(PCLK1)
    RCC_PCLK2Config设置高速 AHB 时钟(PCLK2)
    RCC_AHBPeriphClockCmd使能或者失能 AHB 外设时钟
    RCC_APB2PeriphClockCmd使能或者失能 APB2 外设时钟
    RCC_APB1PeriphClockCmd使能或者失能 APB1 外设时钟
    RCC_APB2PeriphResetCmd强制或者释放高速 APB(APB2)外设复位
    RCC_APB1PeriphResetCmd强制或者释放低速 APB(APB1)外设复位
    RCC_GetFlagStatus检查指定的 RCC 标志位设置与否
    RCC_ClearFlag清除 RCC 的复位标志位
  • 我们想要设置的方案, 比如: 使用外部8M高速晶振, 不分频后, 经过锁相环PLL进行9倍频, 形成系统时钟

示例代码

#include "drv_rcc.h"

void MYRCC_Init(void)
{
    // 配置为新时钟之前,将旧时钟初始化为缺省值
    RCC_DeInit();  //将RCC(复位和时钟控制)寄存器恢复为默认状态(时钟源切换为内部HSI,其他配置清零)。

    // 1. 使能外部晶振(HSE)
    RCC_HSEConfig(RCC_HSE_ON);
    // 等待HSE稳定
    if (ERROR == RCC_WaitForHSEStartUp())
    {
        // 如果配置出错,直接进入死循环
        while (1)
        {
        }
    }
    // 2. 配置PLL(HSE作为输入,倍频到72MHz)
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); // 8MHz * 9 = 72MHz
    // 3. 使能PLL并等待就绪
    RCC_PLLCmd(ENABLE);
    // 等待PLL稳定
    // 没有单独的函数,只能自己手动写
    while (SET != RCC_GetFlagStatus(RCC_FLAG_PLLRDY))
    {
    }
    // 4. 设置系统时钟源为PLL
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
    
    // 等待sysclk稳定
    while (0x08 != RCC_GetSYSCLKSource())
    {
    }
    // 5. 配置APB1和APB2分频(APB1最大36MHz,APB2最大72MHz)
    RCC_HCLKConfig(RCC_SYSCLK_Div1); // AHB = 72MHz
    RCC_PCLK1Config(RCC_HCLK_Div2);  // APB1 = 36MHz
    RCC_PCLK2Config(RCC_HCLK_Div1);  // APB2 = 72MHz
}


http://www.kler.cn/a/612090.html

相关文章:

  • nuxt3网站文章分享微信 ,QQ功能
  • 网络之数据链路层
  • Go 语言规范学习(1)
  • 【Django】教程-2-前端-目录结构介绍
  • opencv简单图形数组识别
  • React 中如何使用ref来访问 DOM 元素或组件实例,有哪些注意事项?
  • Cudann 11.8同时安装tensorflow, pytorch
  • Kafka 的延迟队列、死信队列和重试队列
  • Android设计模式之观察者模式
  • Android 项目缓存问题,某些依赖中的类会报错:Cannot resolve symbol
  • 若依专题——基础应用篇
  • Scala简介与基础
  • 远程办公新体验:用触屏手机流畅操作电脑桌面
  • SpringBoot动态配置数据源的几种实现方式
  • Spring事务与数据库事务的关系
  • 常见邮件协议
  • Oracle Database In-Memory 23ai 新特性
  • 【C++接入大模型】WinHTTP类封装:实现对话式大模型接口访问
  • 适合DBA的brew上手指南
  • (C语言)网络编程之TCP(含三次握手和四次挥手详解)