首页 > 其他分享 >RCC时钟详解

RCC时钟详解

时间:2023-09-19 19:14:26浏览次数:36  
标签:CFGR SYSCLK 详解 寄存器 RCC uint32 时钟

目录

一. STM32时钟树

1.这里主要熟悉SYSCLK的时钟流程即可. (主要是配置好锁相环)

二. 核心寄存器分析

1.RCC_CR时钟控制寄存器

  • RCC_CR寄存器主要是控制时钟状态/使能标志位. 值得注意的是PLLON使能标志位, 后面配置锁相环部分需要先失能.

2.RCC_CFGR时钟配置寄存器

  • RCC_CFGR寄存器主要是负责配置时钟树种, 各个线路上时钟源的选择以及倍频/分频系数.

3.其他寄存器

  • RCC还有时钟中断寄存器, 复位/使能(APB1/APB2)寄存器, 备份区域控制和控制状态寄存器. 这些等后面接触到再做了解.

三. RCC外设驱动

1. 操作寄存器方式驱动

  • 这里以官方的代码作为参考, 从这里可以看出官方将SYSCLK配置为72M, 并将主要的总线上的时钟频率也配置为官方推荐的最大值. 所以外后外设使用无特殊要求, 不需要修改时钟.
static void SetSysClockTo72(void)
{
    __IO uint32_t StartUpCounter = 0, HSEStatus = 0;

    // ① 使能HSE,并等待HSE稳定
    RCC->CR |= ((uint32_t)RCC_CR_HSEON);

    // 等待HSE启动稳定,并做超时处理
    do {
        HSEStatus = RCC->CR & RCC_CR_HSERDY;
        StartUpCounter++;
    } while ((HSEStatus == 0)
        &&(StartUpCounter !=HSE_STARTUP_TIMEOUT));

    if ((RCC->CR & RCC_CR_HSERDY) != RESET) {
        HSEStatus = (uint32_t)0x01;
    } else {
        HSEStatus = (uint32_t)0x00;
    }
    // HSE启动成功,则继续往下处理
    if (HSEStatus == (uint32_t)0x01) {

        //-----------------------------------------------------------
        // 使能FLASH 预存取缓冲区 */
        FLASH->ACR |= FLASH_ACR_PRFTBE;

        // SYSCLK周期与闪存访问时间的比例设置,这里统一设置成2
        // 设置成2的时候,SYSCLK低于48M也可以工作,如果设置成0或者1的时候,
        // 如果配置的SYSCLK超出了范围的话,则会进入硬件错误,程序就死了
        // 0:0 < SYSCLK <= 24M
        // 1:24< SYSCLK <= 48M
        // 2:48< SYSCLK <= 72M */
        FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
        FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
        //------------------------------------------------------------

        // ② 设置AHB、APB2、APB1预分频因子
        // HCLK = SYSCLK
        RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
        //PCLK2 = HCLK
        RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
        //PCLK1 = HCLK/2
        RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

        // ③ 设置PLL时钟来源,设置PLL倍频因子,PLLCLK = HSE * 9 = 72 MHz
        RCC->CFGR &= (uint32_t)((uint32_t)
                                ~(RCC_CFGR_PLLSRC
                                | RCC_CFGR_PLLXTPRE
                                | RCC_CFGR_PLLMULL));
        RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE
                                | RCC_CFGR_PLLMULL9);

        // ④ 使能 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;

        // ⑦ 读取时钟切换状态位,确保PLLCLK被选为系统时钟
        while ((RCC->CFGR&(uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08){
        }
    } else {// 如果HSE启动失败,用户可以在这里添加错误代码出来
    }
}

1. 固件库方式驱动

  • 参考官方寄存器的驱动方式, 用固件库仿写一个可以传参修改SYSCLK时钟的函数. SYSCK要想修改最少要保障一下几点(如第一段代码所示), 详细规整代码如第二段所示.

第一段代码

#include "stm32f10x.h"

int main()
{
    ErrorStatus state;
    
    GPIO_InitTypeDef GPIO_InitStructures;
    
    //要想修改SYSCLK的代码, 必须要重置RCC寄存器, 失能PLL然后设置PLL锁相环时钟源和参数. 最后使能PLL并设置PLLCLK为SYSCLK时钟
    RCC_DeInit();
    RCC_HSEConfig(RCC_HSE_ON);
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_7);
    RCC_PLLCmd(ENABLE);
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
    
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    
    GPIO_InitStructures.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructures.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitStructures.GPIO_Speed = GPIO_Speed_50MHz;
    
    GPIO_Init(GPIOA, &GPIO_InitStructures);
    
    
    RCC_MCOConfig(RCC_MCO_SYSCLK);
}

第二段规整版代码

void HSE_SetSysClock(uint32_t pllmul)
{
    __IO uint32_t StartUpCounter = 0, HSEStartUpStatus = 0;

    // 把RCC外设初始化成复位状态
    RCC_DeInit();

    //使能HSE,开启外部晶振,野火STM32F103系列开发板用的是8M
    RCC_HSEConfig(RCC_HSE_ON);

    // 等待 HSE 启动稳定
    HSEStartUpStatus = RCC_WaitForHSEStartUp();

    // 只有 HSE 稳定之后则继续往下执行
    if (HSEStartUpStatus == SUCCESS) {
//-----------------------------------------------------------------//
        // 这两句是操作FLASH闪存用到的,如果不操作FLASH,这两个注释掉也没影响
        // 使能FLASH 预存取缓冲区
        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

        // SYSCLK周期与闪存访问时间的比例设置,这里统一设置成2
        // 设置成2的时候,SYSCLK低于48M也可以工作,如果设置成0或者1的时候,
        // 如果配置的SYSCLK超出了范围的话,则会进入硬件错误,程序就死了
        // 0:0 < SYSCLK <= 24M
        // 1:24< SYSCLK <= 48M
        // 2:48< SYSCLK <= 72M
        FLASH_SetLatency(FLASH_Latency_2);
//-----------------------------------------------------------------//

        // AHB预分频因子设置为1分频,HCLK = SYSCLK
        RCC_HCLKConfig(RCC_SYSCLK_Div1);

        // APB2预分频因子设置为1分频,PCLK2 = HCLK
        RCC_PCLK2Config(RCC_HCLK_Div1);

        // APB1预分频因子设置为1分频,PCLK1 = HCLK/2
        RCC_PCLK1Config(RCC_HCLK_Div2);

//-----------------设置各种频率主要就是在这里设置-------------------//
        // 设置PLL时钟来源为HSE,设置PLL倍频因子
        // PLLCLK = 8MHz * pllmul
        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, pllmul);
//-------------------------------------------------------------//

        // 开启PLL
        RCC_PLLCmd(ENABLE);

        // 等待 PLL稳定
        while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {
        }

        // 当PLL稳定之后,把PLL时钟切换为系统时钟SYSCLK
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

        // 读取时钟切换状态位,确保PLLCLK被选为系统时钟
        while (RCC_GetSYSCLKSource() != 0x08) {
        }
    } else {
        // 如果HSE开启失败,那么程序就会来到这里,用户可在这里添加出错的代码处理
        // 当HSE开启失败或者故障的时候,单片机会自动把HSI设置为系统时钟,
        // HSI是内部的高速时钟,8MHZ
        while (1) {
        }
    }
}

四. RCC外设驱动总结

  • 无特殊需求, 直接使用使用配置好的时钟频率即可.如果需要修改部分外设, 例如APB1/APB2上面的外设时钟频率只需要调用固件库中的函数, 修改倍频/分频系数即可.(SYSCLK一般不做修改)

标签:CFGR,SYSCLK,详解,寄存器,RCC,uint32,时钟
From: https://www.cnblogs.com/Deng-S/p/17715526.html

相关文章

  • Eclipse Java注释模板设置详解
    设置注释模板的入口:Window->Preference->Java->CodeStyle->CodeTemplate然后展开Comments节点就是所有需设置注释的元素啦。现就每一个元素逐一介绍:文件(Files)注释标签:/***@Title:${file_name}*@Package${package_name}*@Description:${todo}(用一句话描......
  • 详解Spring缓存注解@Cacheable、@CachePut和@CacheEvict
    详解Spring缓存注解@Cacheable、@CachePut和@CacheEvict的使用简介在大型的应用程序中,缓存是一项关键技术,用于提高系统的性能和响应速度。Spring框架提供了强大的缓存功能,通过使用缓存注解可以轻松地集成缓存机制到应用程序中。本文将详细介绍Spring框架中的@Cacheable、@CachePu......
  • 详解RAID6种磁盘阵列模式
    所谓RAID就是RedundantArrayofIndependentDisk的缩写,中文意思是“独立冗余磁盘阵列”,简单来说就是一种利用多个硬盘来提高系统对磁盘的读写速度及其数据安全系数的一种技术。RAID技术开始一般用于服务器或大型工作站上面,但随着RAID技术的不断成熟,现在不少的家用PC的主板都内置......
  • React hooks详解
    importReact,{useEffect,useState}from'react';hook是react16.8的新增特性,他可以让你不在编写class的情况下shiystate以及react的特性Hooks的出现,首先解决了以下问题:告别了令人疑惑的生命周期告别类组件中烦人的this告别繁重的类组件,回归到了熟悉的函数组件reac......
  • 园区交换机之间做NTP时钟同步
    问题:当前我们自己局域网中,每台设备的时钟存在差异,导致查看日志时不清楚事故发生的时间---》解决办法:在核心设备配置NTP服务,让其余二层设备都从核心上同步NTP时间。原理:核心设备向其他设备发送广播,其他设备接收到广播后更新clock时间,与核心进行时间同步。配置如下:core: ntp-......
  • [转]C#Invoke和BeginInvoke应用详解
    最近,在研究Invoke的使用,但是真的是一头雾水,网上看了很多资料,感觉还是看不懂,因为对于入门级的小白,想像不出Invoke的应用场景,更谈不上如何用了?1、Invoke到底是什么?Invoke的本质只是一个方法,方法一定是要通过对象来调用的。一般来说,Invoke其实用法只有两种情况:Control的Invoke......
  • 18_系统时钟管理
    系统时钟管理HAL_Delay()延时HAL_Delay(1000);//延迟一秒如果主函数中还有一些耗时操作,那么实际耗时为:1秒+耗时操作时间vTaskDelay()相对延时每次从任务执行函数vTaskDelay()开始,延时指定时间结束vTaskDelayUntil()绝对延时每隔指定的时间,执行一次调用vTas......
  • 【MyAndroid】AndroidManifest.xml合并规则详解和注意事项
    APK或AndroidAppBundle文件只能包含一个AndroidManifest.xml文件,但AndroidStudio项目可以包含多个清单文件,这些清单文件由主源代码集、build变体和导入的库提供。因此,在构建应用时,Gradle构建系统会将所有清单文件合并成一个清单文件打包到应用中。清单合并工具遵循某些......
  • ipmitool 参数详解和常用命令列举
    ipmitool是一种可用在linux系统下的ipmi平台管理工具,它支持ipmi1.5规范(最新的规范为ipmi2.0),通过它可以实现获取传感器的信息、显示系统日志内容、网络远程开关机等功能。 [root@localhost~]#ipmitool-hipmitoolversion1.8.18usage:ipmitool[options...]<co......
  • SQL update select结合语句详解及应用
    SQLupdateselect结合语句详解及应用 QLupdateselect语句最常用的update语法是:12UPDATETABLE_NAMESETcolumn_name1=VALUEWHRERcolumn_name2=VALUE如果我的更新值Value是从一条select语句拿出来,而且有很多列的话,用这种语法就很麻烦第一,要sel......