STM32---时钟树

写在前面:一个 MCU 越复杂,时钟系统也会相应地变得复杂,如 STM32F1 的时钟系统比较复杂,不像简单的 51 单片机一个系统时钟就 可以解决一切。对于 STM32F1 系列的芯片,其有多个时钟源,构成了一个庞大的是时钟树。本节我们将学习时钟树的相关的内容。

目录

一、简述时钟

二、时钟树详解

2.1时钟源          

2.2 PLL锁相环

2.3系统时钟SYSCLK

2.4 APB1、APB2时钟

2.5 其他时钟        

三、配置系统时钟

 3.1系统时钟配置步骤

3.2利用 HAL 库配置 STM32F1 时钟系统

3.3外设时钟使能


一、简述时钟

        时钟树简图:

1、时钟源 

HSE(高速外部振荡器)4-16MHz晶体或陶瓷
LSE(低速外部振荡器)32.768KHz晶体或陶瓷
HSI(高速内部振荡器)8MHzRC电路
LSI(低速内部振荡器)40KHzRC电路

         对于 STM32F1,输入时钟源(Input Clock)主要包括 HSI,HSE,LSI,LSE。

        从时钟频率来分可以分为高速时钟源和低速时钟源,其中 HSI、HSE 高速时钟,LSI 和 LSE 是低速时钟。

        从时钟来源可分为外部时钟源和内部时钟源,外部时钟源就是从外部通过接晶振的方式获取时钟源,其中 HSE 和 LSE 是外部时钟源;其他是内部时钟源,芯片上电即可产生,不需要 借助外部电路。

        晶体时钟的特点是:成本高、稳定、精确,如果可以首选外部时钟;

2、PLL锁相环

        此处锁相环的主要作用是倍频,对于相同的稳定运行的电路,时钟频率越高,指令的执行速度越快, 单位时间能处理的功能越多。对于STM32来说,其系统时钟不超过72MHz;而时钟源的时钟频率最多也就16MHz,无法达到芯片的要求,此时就需要倍频器将外部时钟频率进行倍频,再传给系统时钟;

3、系统时钟SYSCLK

        STM32 的系统时钟 SYSCLK 为整个芯片提供了时序信号。系统时钟的信号来源分别为:HSE、HSI以及经过分频器的输出信号;AHB、APB1、APB2、内核时钟等时钟通过系统时钟分 频得到。

4、HCLK(AHB总线)

        AHB总线将来自系统时钟的信号进行分频或不分频通过总线再分给其他外设、系统内核时钟或者APB1、APB2上的时钟;

5、LSI、LSE

      低速内部RC(LSI RC)振荡器,可以用于驱动独立看门狗,或通过程序选择驱动 RTC;

       LSE 振荡器时钟,也可以驱动 RTC;

二、时钟树详解

 一个简化的 STM32F1 时钟系统。图中已经把我们主要关注几处标注出来。

A 部分表示其他电路需要的输入源时钟信号;

B 为一个特殊的振荡电路“PLL”,由几个部分构成;

C 为我们重点需要关注的 MCU 内的注释中“SYSCLK”;AHB 预分频器将 SYSCLK 分频或不 分频后分发给其他外设进行处理;

D 和 E 部分分 别为定时器等外设的时钟源 APB1/APB2;

F 部分的 Cortex-M 内核系统的时钟;

G 是 STM32 的时钟输出功能。

2.1时钟源          

        A部分为四个时钟源,高速外部振荡器(8MHz)、低速外部振荡器(32.768kHz) 石英晶体,主要作用于 RTC 的时钟源。高速内部振荡器 由内部 RC 振荡器产生,频率为 8MHz。低速内部振荡器由内部 RC 振荡器产生,频率为 40kHz,可作为独立看门狗的时钟源。

        由高速振荡器输出两路信号,分别直接连接SYSLCK系统时钟,以及进入PLL锁相环;

2.2 PLL锁相环

PLL锁相环由三部分组成,分别为:PLLXTPRE、PLLSRC、PLLMUL;

PLLXTPRE:HSE分频器作为PLL输入,专门用于 HSE,0:HSE不分频;1:HSE2分频;

PLLSRC:PLL时钟源的选择器;0:HSI经2分频作为PLL时钟源;1:HSE作为PLL时钟源;

PLLMUL:用于配置锁相环倍频系数,ST 设置它的 有效倍频范围为 2~16 倍;

涉及寄存器为RCC_CFGR(第16-21位) 

2.3系统时钟SYSCLK

 SYSCLK 为整个芯片提供了时序信号。对于相同的稳定运行的电路,时钟频率越高,指令的执行速度越快, 单位时间能处理的功能越多。STM32 的系统时钟是可配置的,在STM32F1 系列中,它可以为 HSI、PLLCLK、HSE 中的一个。可选时钟信号有外部高速时钟 HSE(8M)、内部高速时钟 HSI(8M)和经过倍频的 PLL CLK(72M),选择 PLL CLK 作为系统时钟,此时系统时钟的频率为 72MHz。

涉及寄存器为RCC_CFGR 的位 SW[1:0]

2.4 APB1、APB2时钟

 AHB、APB1、APB2、内核时钟等时钟通过系统时钟分频得到。

         系统时钟信号来到的 AHB 预分频器,可以选择的分频系数为 1,2,4,8,16,32,64,128,256,也可以选择不分频;AHB 总线时 钟达到最大的 72MHz。

涉及的寄存器为RCC_CFGR 的位 HPRE[3:0]

        APB1 总线时钟,由 HCLK 经过标号 E 的低速 APB1 预分频器得到,分频因子可以选择 1, 2,4,8,16,这里我们选择的是 2 分频,所以 APB1 总线时钟为 36M。由于 APB1 是低速总线 时钟,所以 APB1 总线最高频率为 36MHz,片上低速的外设就挂载在该总线上,例如有看门狗 定时器、定时器 2/3/4/5/6/7、RTC 时钟、USART2/3/4/5、SPI2(I2S2)与 SPI3(I2S3)、I2C1 与 I2C2、 CAN、USB 设备和 2 个 DAC。

        APB2 总线时钟,由 HCLK 经过标号 F 的高速 APB2 预分频器得到,分频因子可以选择 1, 2,4,8,16,这里我们选择的是 1 即不分频,所以 APB2 总线时钟频率为 72M。与 APB2 高速 总线链接的外设有外部中断与唤醒控制、7 个通用目的输入/输出口(PA、PB、PC、PD、PE、PF 和 PG)、定时器 1、定时器 8、SPI1、USART1、3 个 ADC 和内部温度传感器。

涉及的寄存器为RCC_CFGR 的位 PPRE-PPRE2[2:0]

2.5 其他时钟        

         此外,AHB总线还与一些外设直接相连,作为外设的时钟,比如ADC,在传入ADC之前,还需要接入ADC预分频器;

涉及的寄存器为RCC_CFGR 的位ADCPRE[1:0]:

最后为时钟树的全速USB OTG预分频,以及为控制器时钟输出;

        USBCLK,是一个通用串行接口时钟,时钟来源于 PLLCLK。STM32F103 内置 全速功能的 USB 外设,其串行接口引擎需要一个频率为 48MHz 的时钟源。该时钟源只能从 PLL 输出端获取,可以选择为 1.5 分频或者 1 分频,也就是,当需要使用 USB 模块时,PLL 必须使能,并且时钟频率配置为 48MHz 或 72MHz。

         MCO 输出内部时钟,STM32 的一个时钟输出 IO(PA8),它可以选择一个时钟信号输出,可以选择为 PLL 输出的 2 分频、HSI、HSE、或者系统时钟。这个时钟可以用来给外部其他系统提供时钟源。 

涉及的寄存器为RCC_CFGR 的位OTGFSPRE、MCO:

             RTC 定时器,其时钟源为 HSE/128、LSE 或 LSI。时钟安全系统、自由运行时钟FCLK;

         这些寄存器只是对于使用时钟是一个整体的设置,具体到某个外设的时钟,还需要对应的寄存器设置。 

三、配置系统时钟

        在STM32库函数中,封装了部分寄存器的功能函数,其中有:

时钟源、锁相环:HAK_RCC_OssConfig()

系统时钟、总线:HAK_RCC_ClockConfig()

使能外设时钟:HAK_RCC_PPP_CLK_ENABLE()

扩展外设时钟(RTC/ADC/USB):HAL_RCCCEX_PeriphCLKConfig()

 3.1系统时钟配置步骤

1、配置HSE_VALVE;

2、调用System Init()函数;

3、选择时钟源,配置PLL;

4、选择系统时钟源,配置总线分频器;

5、配置扩展外设时钟;

其中,重要的是步骤345 ,其封装在时钟设置函数 sys_stm32_clock_init。

我们拿出一个例程中对于该函数的设置来进行判断:

/** * @brief 系统时钟初始化函数

* @param plln: PLL 倍频系数(PLL 倍频), 取值范围: 2~16

中断向量表位置在启动时已经在 SystemInit()中初始化

* @retval 无 */

void sys_stm32_clock_init(uint32_t plln)

{

HAL_StatusTypeDef ret = HAL_ERROR;

RCC_OscInitTypeDef rcc_osc_init = {0};

RCC_ClkInitTypeDef rcc_clk_init = {0};

rcc_osc_init.OscillatorType = RCC_OSCILLATORTYPE_HSE; /* 选择要配置 HSE */ rcc_osc_init.HSEState = RCC_HSE_ON; /* 打开 HSE */

rcc_osc_init.HSEPredivValue = RCC_HSE_PREDIV_DIV1; /* HSE 预分频系数 */ rcc_osc_init.PLL.PLLState = RCC_PLL_ON; /* 打开 PLL */

rcc_osc_init.PLL.PLLSource = RCC_PLLSOURCE_HSE; /* PLL 时钟源选择 HSE */ rcc_osc_init.PLL.PLLMUL = plln; /* PLL 倍频系数 */

ret = HAL_RCC_OscConfig(&rcc_osc_init); /* 初始化 */

if (ret != HAL_OK)

{

while (1); /* 时钟初始化失败后,程序将可能无法正常执行,可以在这里加入自己的处理 */

}

/* 选中 PLL 作为系统时钟源并且配置 HCLK,PCLK1 和 PCLK2*/

rcc_clk_init.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);

rcc_clk_init.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;/* 设置系统时钟来自 PLL */

        函数 sys_stm32_clock_init 就是用户的时钟系统配置函数,除了配置 PLL 相关参数确定 SYSCLK 值之外,还配置了 AHB、APB1 和 APB2 的分频系数,也就是确定了 HCLK,PCLK1 和 PCLK2 的时钟值。至于为何要这样配置,我们在底下这节进行说明:

3.2利用 HAL 库配置 STM32F1 时钟系统

一般步骤:

1) 配置时钟源相关参数:调用函数 HAL_RCC_OscConfig()。

HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct);

RCC_OscInitTypeDef 的定义:

        在3.1系统时钟配置步骤中, sys_stm32_clock_init就是对上述结构体内容的配置;通过函数的该段程序,我们开启了 HSE 时钟源,同时选择 PLL 时钟源为 HSE,然后把 sys_stm32_clock_init 的形参直接设置作为 PLL 的参数 M 的值,这样就达到了设置 PLL 时钟源相关参数的目的。

2) 配置系统时钟源以及 SYSCLK、AHB、APB1 和 APB2 的分频系数:调用函数 HAL_RCC_ClockConfig()。

HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency);

        该函数有两个形参,第一个形参 RCC_ClkInitStruct 是结构体 RCC_ClkInitTypeDef 类型指 针变量,用于设置 SYSCLK 时钟源以及 SYSCLK、AHB、APB1 和 APB2 的分频系数。第二个 形参 FLatency 用于设置 FLASH 延迟。

RCC_ClkInitTypeDef 结构体定义

        同样,在3.1系统时钟配置步骤中, sys_stm32_clock_init对上述结构体内容的配置; 

        第二个参数 FLatency 的含义,为了使 FLASH 读写正确(因为 72Mhz 的时钟比 Flash 的操作速度 24Mhz 要快得多,操作速度不匹配 容易导致 Flash 操作失败),所以需要设置延时时间。

3.3外设时钟使能

        在配置好时钟系统之后,如果我们要使用某些外设, 例如 GPIO,ADC 等,我们还要使能这些外设时钟。这里大家必须注意,如果在使用外设之前 没有使能外设时钟,这个外设是不可能正常运行的。

        在 STM32F1 的 HAL 库中,外设时钟使能操作都是在 RCC 相关固件库文件头文件 STM32F1xx_hal_rcc.h 定义的,首先,我们来看看 GPIOA 的外设时钟使能宏定义标识符:

#define __HAL_RCC_GPIOA_CLK_ENABLE() do { \

__IO uint32_t tmpreg; \

SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPAEN);\

tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPAEN);\

UNUSED(tmpreg); \

} while(0U)

        这段代码主要是定义了一个宏定义标识符__HAL_RCC_GPIOA_CLK_ENABLE(),它的核心操作是通过下面这行代码实现的: SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPAEN);

        这行代码的作用是,设置寄存器 RCC->APB2ENR 的相关位为 1,至于是哪个位,是由宏定 义标识符 RCC_APB2ENR_IOPAEN 的值决定的。 RCC_APB2ENR_IOPAEN的值为2,位 2 的作用是用来使用 GPIOA 时钟,那么我们只需要在我们的用户程序中调用宏定义标识符就可以实现 GPIOA 时钟使能。使用方法为:

__HAL_RCC_GPIOA_CLK_ENABLE(); /* 使能 GPIOA 时钟 *

        对于其他外设,同样都是在 STM32F1xx_hal_rcc.h 头文件中定义,大家只需要找到相关宏定义标识符即可。

        我们使用外设的时候需要使能外设时钟,如果我们不需要使用某个外设,同样我们可以禁止某个外设时钟。禁止外设时钟使用方法和使能外设时钟非常类似,同样是头文件中定义的宏定义标识符。

例如:

#define __HAL_RCC_GPIOA_CLK_DISABLE();/*禁止 GPIOA 时钟 *

总结:本节我们学习了STM32的时钟树,从简图学习,再到整个时钟树的详解,包括其功能,涉及的相关寄存器,以及配置的系统时钟的方法步骤,再后面的学习中,我们将经常使用时钟树,因此在后面我们也会熟练的掌握!

创作不易,还请大家多多点赞支持!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/205111.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一个软件测试练手项目——学生信息管理系统测试,卷起来啊

免费分享一个练手项目,学生信息管理系统,获取方式在文末 1.引言 1.1项目目的 软件测试是为了在软件投入生产性运行之前,尽可能多地发现软件的错误。该项目的目的是给学习软件测试的朋友练手用 1.2 项目背景 随着学校的规模不断扩大&…

技巧-GPU显存和利用率如何提高和batch_size/num_works等参数的实验测试

目录 简介实验测试显存占用问题GPU占用率波动问题num_work不是越大越好 总结 本专栏为深度学习的一些技巧,方法和实验测试,偏向于实际应用,后续不断更新,感兴趣童鞋可关,方便后续推送 简介 在PyTorch中使用多个GPU进行模型训练时,各个参数和指标之间存在一定的关系…

安防视频监控/磁盘阵列/集中云存储平台EasyCVR设备录像保活不生效原因是什么?该如何解决?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等,以及支持厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

18、串口通信

串口介绍 串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信。 单片机的串口可以使单片机与单片机,单片机与电脑、单片机与各式各样的模块互相通信,极大的扩展了单片机的应用范围&…

Linux基础操作三:Linux操作命令-目录文件操作

1、关机和重启 关机shutdown -h now 立刻关机shutdown -h 5 5分钟后关机poweroff 立刻关机 重启shutdown -r now 立刻重启shutdown -r 5 5分钟后重启reboot 立刻重启 2、帮助 --help命令shutdown --help:…

MySQL表的查询、更新、删除

查询 全列查询 指定列查询 查询字段并添加自定义表达式 自定义表达式重命名 查询指定列并去重 select distinct 列名 from 表名 where条件 查询列数据为null的 null与 (空串)是不同的! 附:一般null不参与查询。 查询列数据不为null的 查询某列数据指定…

【JUC】十九、volatile与内存屏障

文章目录 1、volatile的两大特性2、volatile的四大内存屏障3、分类4、happens-before之volatile变量重排规则5、读写屏障插入策略 1、volatile的两大特性 被volatile修饰的变量有两大特点: 可见性有序性 关于volatile的可见性,也即volatile的内存语义…

线性回归 调试方法

调试方法 特征缩放 对于某些不具有比较性的样本特征 x i x_i xi​ (比如对其他的x来说 x i x_i xi​ 相当大或者相当小),梯度下降的过程可能会非常漫长,并且可能来回波动才能最后收敛到全局的最小值。 在这样的情况下&#xff…

8年经验之谈 —— Redis的性能测试与优化!

Redis作为一种高性能的Key-Value数据库,一直受到众多开发者和企业的青睐。然而,在高并发、大数据存储的应用场景中,如何测试并优化Redis的性能,成为了问题。本文将从测试与优化两个方面来讲解如何达到最优的Redis性能。 一、性能…

Android Studio Giraffe版本遇到的问题

背景 上周固态硬盘挂了,恢复数据之后,重新换了新的固态安装了Win11系统,之前安装的是Android Studio 4.x的版本,这次也是趁着新的系统安装新的Android开发工具。 版本如下: 但是打开以前的Android旧项目时&#xff…

Selenium定位元素的方法css和xpath的区别!

selenium是一种自动化测试工具,它可以通过不同的定位方式来识别网页上的元素,如id、name、class、tag、link text、partial link text、css和xpath。 css和xpath是两种常用的定位方式,它们都可以通过元素的属性或者层级关系来定位元素&#…

Python 自动化测试全攻略:五种自动化测试模型实战详解!

随着移动互联网的发展,软件研发模型逐步完善,软件交付质量越来越受到软件公司的重视,软件测试技术特别是自动化测试技术开始在软件系统研发过程中发挥着越来越重要的作用。 与传统的手工测试技术相比,自动化测试具备了良好的可操…

考试复习

选择20道 填空10道 判断10道 简答4-5道 编程题2道 一、选择题 1.js中更改一个input框的值&#xff1a; <input ida type"text" value"123456"> 通过a.value改变他的值 方法&#xff1a; 在script标签中通过id获得该输入框对象&#xff0c;然…

从0到字节跳动30W年薪,我在测试行业“混”的第5个年头····

一些碎碎念 什么都做了&#xff0c;和什么都没做其实是一样的&#xff0c;走出“瞎忙活”的安乐窝&#xff0c;才是避开弯路的最佳路径。希望我的经历能帮助到有需要的朋友。 在测试行业已经混了5个年头了&#xff0c;以前经常听到开发对我说&#xff0c;天天的点点点有意思没…

探索前端设计的新境界——介绍IVueUI工具助力Vue页面设计

在快速发展的前端领域&#xff0c;Vue.js作为一款渐进式JavaScript框架&#xff0c;一直备受开发者喜爱。然而&#xff0c;在Vue前端开发的旅程中&#xff0c;页面设计常常是一个不可避免的挑战。今天&#xff0c;我要向大家介绍一款令Vue前端开发者受益匪浅的工具——www.ivue…

Peter算法小课堂—高精度乘法

给大家看个小视频13 高精度算法 乘法_哔哩哔哩_bilibili 乘法竖式 大家觉得Plan A好&#xff0c;还是Plan B好呢&#xff08;对于计算机来说&#xff09;&#xff1f;那显然是B啦 x*y问题 mul思路&#xff1a;mul()函数返回x数组乘y数组的积&#xff0c;保存在z数组。根据上…

jupyter notebook 添加conda环境变量为内核(kenel)

第一步&#xff1a;安装ipykernel 在激活环境后&#xff0c;需要安装ipykernel包&#xff0c;以便将Conda环境添加到Jupyter Notebook中。使用以下命令安装&#xff1a; pip install ipykernel第二步&#xff1a;将Conda环境添加到Jupyter 需要将Conda环境添加到Jupyter Not…

python爬取robomaster论坛数据,作为后端数据

一. 内容简介 python爬取robomaster论坛数据&#xff0c;作为后端数据 二. 软件环境 2.1vsCode 2.2Anaconda version: conda 22.9.0 2.3代码 三.主要流程 3.1 接口分析 # 接口分析 # 全部数据 # https://bbs.robomaster.com/forum.php?modforumdisplay&fid63 2…

LeetCode(46)汇总区间【区间】【简单】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 汇总区间 1.题目 给定一个 无重复元素 的 有序 整数数组 nums 。 返回 恰好覆盖数组中所有数字 的 最小有序 区间范围列表 。也就是说&#xff0c;nums 的每个元素都恰好被某个区间范围所覆盖&#xff0c;并且不存在属于某…

如何通过linux调用企业微信发送告警消息

一、前期准备 1、企业微信具备管理企业权限。 2、服务器有公网IP或者可以将本机端口通过net映射到公网。 二、通过脚本向企业微信发送消息 1、创建sh脚本用来发送消息。 vim 2.sh 注意&#xff1a;脚本中xxxx信息需要在企业微信管理后台获取。 #!/bin/bash # 设置企业…