【STM32标准库】【基础知识】时钟系统

2023-11-16


文章基于适用于STM32F4系列,作者使用STM32F401CCU6开发板。
本文章基于此系列和开发板展开讨论。

时钟

时钟的作用

学习过数电课程的应该知道,时钟对于时序逻辑电路的重要性。
时钟在本质上就是一个确定频率(周期)的波形,在数字电路中是以方波的形式出现的。
时钟为存在先后次序的电路(逻辑关系)提供了一个时间基准。缺失了这个基准时序逻辑电路将无法正常运行

时钟的产生

产生最初时钟的方式常用的有两种。

一是RC震荡回路,这是利用电容的充放电产生周期性的波形。 它对于电容和电阻的精度要求高,而且震荡频率稳定性也欠佳,优点在于可以在制造完成后改变其频率

二是石英晶体震荡器,简称晶振,这种震荡器利用了石英晶体的压电效应
无源晶振可以将其认为是一个检波器,允许特定频率的信号通过,加上放大电路(起振是利用电路的固有噪声)就可以产生时钟信号了。
有源晶振就是将放大器和无源晶振打包起来。
优点是成本低,精度高(再好的RC震荡电路也无法比及同水平的晶振),缺点是因为是利用特定形状的晶体,因此无法在出厂后改变其频率

三是锁相环(PLL),为了解决前两个方案的缺点,聪明的人们发明了一种叫做锁相环的东西,具体原理,这里只需要知道它可以时两个频率接近,相位接近的信号变成同相位同频率的信号。或者接近频率乘倍数的信号相位相同(其实就是跳过一个或几个周期,利用其边沿锁相),就像这样
上面的是晶振输入的标准信号

在这里插入图片描述

我们可以使用PLL进行分频和倍频操作。分频可以使用数电中的分频器然后送入锁相环进行锁相,倍频可以利用VCO产生高频时钟然后分频后送入PLL锁相

因此,我们可以使用这3个系统产生单片机所使用的时钟信号。

F4系列的时钟系统

时钟源

STM32F4系列有多个时钟源用于不同需求的外设

下表中的频率为本单片机所支持的,如果使用其他单片机请自行查询

缩写 中文名称 频率 作用
HSI 高速内部时钟 默认16MHz 备用系统时钟
HSE 高速外部时钟 最大50MHz(最大晶振为25MHz) PLL倍频后做系统时钟
LSI 低速内部时钟 32KHz 看门狗用
LSE 低速外部时钟 32.768KHz RTC用

总线

STM32F4系列有两种总线,AHB(高性能总线)用于高性能模块之间的连接,APB(外设总线)用于连接低速设备

AHB的时钟是系统时钟经过分频得到的,一般情况是与系统时钟相同。 AHB最高工作频率同系统时钟

APB有2根总线,他们的时钟不相同。 APB2的时钟频率大于APB1
APB2最高工作频率为84MHz, APB1最高工作频率为42MHz,

APB1和APB2可以分别分频AHB的时钟

下表中的频率为本单片机所支持的,如果使用其他单片机请自行查询
这是在标准库中查询时可能用到的一些名词解释

缩写 名称 最大频率 来源
SYSCLK 系统时钟 168MHz HSI,或HSE,或Main PLL直接驱动
HCLK 高速设备的时钟(如CPU) SYSCLK 经AHB预分频器分频SYSCLK
PCLK1 APB1时钟 42MHz 经APB1预分频器分频HCLK
PCLK2 APB2时钟 84MHz 经APB2预分频器分频HCLK

关于挂载在APB1/2总线下的计时器有一点需要注意

如果APB1/2没有分频,也就是分频系数的值为1,分频选项的宏定义一般为DIV1结尾
则定时器的时钟就是APB1/2的时钟

如果分频了,就是分频选项的值为2或4或8或16,分频选项的宏定义一般为DVI2/DVI4等
则定时器的时钟频率为APB1/2的时钟的两倍

标准库的时钟设置

内部高速时钟设置

注意:需要找到自己单片机型号所对应的宏定义处

输入HSI_VALUE跳转到定义处即可修改内部RC震荡器的数值(单位Hz)

外部高速时钟设置

注意:需要找到自己单片机型号所对应的宏定义处

输入HSE_VALUE跳转到定义处即可修改外部晶振的数值(单位Hz)

注意,因为系统时钟是由外部晶振通过PLL倍频得到的,因此需要修改系统时钟和PLL参数

输入SystemCoreClock跳转到定义处即可修改系统时钟的值(单位Hz)

输入PLL_M跳转到定义处即可修改有关系统时钟的PLL倍频选项
输入PLL_N跳转到定义处即可修改有关系统时钟的PLL倍频选项
输入PLL_P跳转到定义处即可修改有关系统时钟的PLL倍频选项
输入PLL_Q跳转到定义处即可修改有关系统时钟的PLL倍频选项

注意这四个的取值是有范围的
2 <= PLL_Q <= 15

2 <= PLL_M <= 63

192 <= PLL_N <= 432

PLL_P是2, 4, 6, 8其中之一

PLL的VCO的频率的计算公式是

PLL_VCO = [ ( HSE或HSI ) / PLL_M ] * PLL_N
其中HSE是外部晶振频率(单位MHz)
其中HSI是内部RC振荡器频率(单位MHz)

系统时钟频率是PLL_VCO经过分频后得到的
计算公式如下

SYSCLK = PLL_VCO / PLL_P

也就是说

SYSCLK = [ ( HSE或HSI ) / PLL_M ] * PLL_N / PLL_P

PLLQ是关于USB,SDIO,RNG的时钟,其值为

PLL_VCO / PLLQ

AHB时钟设置

注意:需要找到自己单片机型号所对应的宏定义处

输入**SetSysClock()**跳转到定义处,在下面有个带注释的寄存器操作代码

 /* HCLK = SYSCLK / 1*/
  RCC->CFGR |= RCC_CFGR_HPRE_DIV1;

也就是这个,直接修改RCC_CFGR_HPRE_DIV1为自己需要的分频数,可以为

#define  RCC_CFGR_HPRE_DIV1                  ((uint32_t)0x00000000)        /*!< SYSCLK not divided */
#define  RCC_CFGR_HPRE_DIV2                  ((uint32_t)0x00000080)        /*!< SYSCLK divided by 2 */
#define  RCC_CFGR_HPRE_DIV4                  ((uint32_t)0x00000090)        /*!< SYSCLK divided by 4 */
#define  RCC_CFGR_HPRE_DIV8                  ((uint32_t)0x000000A0)        /*!< SYSCLK divided by 8 */
#define  RCC_CFGR_HPRE_DIV16                 ((uint32_t)0x000000B0)        /*!< SYSCLK divided by 16 */
#define  RCC_CFGR_HPRE_DIV64                 ((uint32_t)0x000000C0)        /*!< SYSCLK divided by 64 */
#define  RCC_CFGR_HPRE_DIV128                ((uint32_t)0x000000D0)        /*!< SYSCLK divided by 128 */
#define  RCC_CFGR_HPRE_DIV256                ((uint32_t)0x000000E0)        /*!< SYSCLK divided by 256 */
#define  RCC_CFGR_HPRE_DIV512                ((uint32_t)0x000000F0)        /*!< SYSCLK divided by 512 */

默认情况下,HCLK = SYSCLK

APB1/2时钟设置

注意:需要找到自己单片机型号所对应的宏定义处

输入SetSysClock() 跳转到定义处,在下面有个带注释的寄存器操作代码

   /* PCLK2 = HCLK / 1*/
    RCC->CFGR |= RCC_CFGR_PPRE2_DIV1;
    
    /* PCLK1 = HCLK / 2*/
    RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;

修改RCC_CFGR_PPRE2_DIV1RCC_CFGR_PPRE1_DIV2即可
APB2可以取值为

#define  RCC_CFGR_PPRE2_DIV1                 ((uint32_t)0x00000000)        /*!< HCLK not divided */
#define  RCC_CFGR_PPRE2_DIV2                 ((uint32_t)0x00008000)        /*!< HCLK divided by 2 */
#define  RCC_CFGR_PPRE2_DIV4                 ((uint32_t)0x0000A000)        /*!< HCLK divided by 4 */
#define  RCC_CFGR_PPRE2_DIV8                 ((uint32_t)0x0000C000)        /*!< HCLK divided by 8 */
#define  RCC_CFGR_PPRE2_DIV16                ((uint32_t)0x0000E000)        /*!< HCLK divided by 16 */

APB1可以取值为

#define  RCC_CFGR_PPRE1_DIV1                 ((uint32_t)0x00000000)        /*!< HCLK not divided */
#define  RCC_CFGR_PPRE1_DIV2                 ((uint32_t)0x00001000)        /*!< HCLK divided by 2 */
#define  RCC_CFGR_PPRE1_DIV4                 ((uint32_t)0x00001400)        /*!< HCLK divided by 4 */
#define  RCC_CFGR_PPRE1_DIV8                 ((uint32_t)0x00001800)        /*!< HCLK divided by 8 */
#define  RCC_CFGR_PPRE1_DIV16                ((uint32_t)0x00001C00)        /*!< HCLK divided by 16 */

也就是说,APB1默认是2倍分频,APB2默认是不分频

默认值

前提:使用25MHz的外部晶振,没有修改标准库函数
根据上面的式子可以计算出各个时钟的默认值,这里只给结果了

缩写 名称 默认频率(单位MHz)
PLL_VCO 锁相环的压控振荡器 336
SYSCLK 系统时钟 84
HCLK AHB时钟 84
PCLK1 APB1时钟 42
PCLK2 APB2时钟 84

因此STM32所有的定时器的时钟频率均为84MHz,也就是系统时钟频率

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【STM32标准库】【基础知识】时钟系统 的相关文章

  • Mac电脑M1芯片Python环境搭建

    一 安装miniforge 1 从github中下载miniforge 也可以在我的阿里云盘中下载miniforge 提取密码为 R6pb 2 打开终端 找到下载的文件的位置 进行安装 进入下载位置 cd XXX Downloads lis
  • flutter 打包安装后闪退问题

    问题 升级flutter插件后 生成release版apk 安装到手机启动flutter代码时出现闪退问题 log日志回报一系列的so库错误 原因 具体原因我不知道到什么原理造成 个人理解的应该是flutter sdk 版本问题 解决 在a
  • Linux查看文件大小的命令du的简单介绍

    文章目录 官方介绍 简单介绍 常用选项 与单位相关的选项 apparent size B block size SIZE b bytes k m 与遍历深度相关的选项 s summarize d max depth N h human re
  • 时间序列突变点检测

    我对时间序列异常点算法小结 基于时间序列的异常检测算法小结 Jasminexjf的博客 CSDN博客 基于时间序列的异常检测算法 当前异常检测类型 最重要的异常类型 例如意外的峰值 下降 趋势变化和水平转移 我主要研究的是负荷预测的突变点
  • mysql8的卸载

    mysql8的卸载 卸载mysql8 卸载mysql8 先在Windows界面使用快捷键Windows R搜索services msc进入服务 找到mysql并停止它 然后进入C盘将隐藏文件显示出来 进入装有mysql文件夹的三个文件并删除
  • 软件测试基础与基于生命周期的软件测试

    软件测试基础 2 1软件测试 2 1 1定义 在规定的条件下对程序进行操作 以发现程序是否满足设计错误 衡量软件质量并对其是否满足设计要求进行评估的过程 2 1 2目的 发现缺陷 提高质量 验证是否满足需求 建立软件质量的信心 2 1 3原

随机推荐