“我们一直都说STM32有一个非常复杂的时钟系统,然而在原子或者野火的例程中,只要涉及到时钟,我们却只能看到类似的库函数调用,如RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);这个仅仅只是起到开启挂载在APB2线上的USART1时钟的作用罢了,APB2的时钟频率是多少我们并不知道”

我们先来了解一些stm32的时钟结构。
  • 1
  • 2

这个图说明了STM32的时钟走向,从图的左边开始,从时钟源一步步分配到外设时钟。 
从时钟频率来说,又分为高速时钟和低速时钟,高速时钟是提供给芯片主体的主时钟,而低速时钟只是提供给芯片中的RTC(实时时钟)及独立看门狗使用。

从芯片角度来说,时钟源分为内部时钟与外部时钟源 ,内部时钟是在芯片内部RC振荡器产生的,起振较快,所以时钟在芯片刚上电的时候,默认使用内部高速时钟。而外部时钟信号是由外部的晶振输入的,在精度和稳定性上都有很大优势,所以上电之后我们再通过软件配置,转而采用外部时钟信号。

所以,STM32有以下4个时钟源: 
高速外部时钟(HSE):以外部晶振作时钟源,晶振频率可取范围为4~16MHz,我们一般采用8MHz的晶振。 
高速内部时钟(HSI): 由内部RC振荡器产生,频率为8MHz,但不稳定。 
低速外部时钟(LSE):以外部晶振作时钟源,主要提供给实时时钟模块,所以一般采用32.768KHz。 
低速内部时钟(LSI):由内部RC振荡器产生,也主要提供给实时时钟模块,频率大约为40KHz。

时钟频率当然是可以通过代码来配置的,然而main函数中我们却没看到配置时钟的相关代码。这说明了我们一直用的是默认的设置,也就是说,在进入main函数之前时钟频率就已经被设置好了。这时候,大家应该都已经想到了,就是stm32的启动文件,startup_stm32f10x_hd.s。于是我们打开这个文件,会发现有这么一块用汇编写的代码。

      Reset_Handler   PROCEXPORT  Reset_Handler             [WEAK]IMPORT  __mainIMPORT  SystemInitLDR     R0, =SystemInitBLX     R0               LDR     R0, =__mainBX      R0ENDP
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

从这里我们可以看到,我们的程序在进入到main函数之前,先要执行systeminit,跳转到这个函数的定义。里面的代码是对寄存器直接进行操作了,我查找了用户手册,寄存器的相关配置说明写在了注释里面(IDE里面文字设置为ANSI格式了,直接复制过来会出现乱码,大家将就下看看图片吧)

这里涉及到了两个寄存器RCC_CR,与RCC_CFGR,分别是时钟控制寄存器与时钟配置寄存器,它们的作用顾名思义,就是起到了控制和配置时钟的作用。想具体了解寄存器每一位的功能,请查阅用户手册。 
这段代码实现了时钟的初始化,也就是所谓的默认设置了。 
执行完后,我们继续往下走

  /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers *//* Configure the Flash Latency cycles and enable prefetch buffer */SetSysClock();
  • 1
  • 2
  • 3

我们可以看到,这里还有一个函数,看它的命名,显然就是对时钟进行设置的函数。 
我们看一下它的实现过程。

因为我们并没有这些宏定义,所以相当于执行了一个nop函数。显然,在这个程序中,这个函数并没有起到改变时钟配置的作用,我们用的还是初始化的默认配置。 
到这里,关于stm32系统时钟的默认设置就已经结束了。 
对照着时钟树,我们结合代码来回顾一下。

首先从左端的OSC_OUT和OSC_IN开始,假设我们外接的是8MHz的晶振,两个引脚分别接到外部晶振的两端。

8MHz的时钟遇到了第一个分频器PLLXTPRE(HSE divider for PLL entry),在这个分频器中,可以通过寄存器配置,选择它的输出。它的输出时钟可以是对输入时钟的二分频或不分频。本例子中,我们选择不分频,所以经过PLLXTPRE后,还是了8MHz的时钟。

8MHz的时钟遇到开关PLLSRC(PLL entry clock source),我们可以选择其输出,输出为外部高速时钟(HSE)或是内部高速时钟(HSI)。这里选择输出为HSI(HSE经二分频后变成了4MHz的时钟),接着遇到锁相环PLL,具有倍频作用,在这里我们可以输入倍频因子PLLMUL(PLL multiplication factor),经过PLL的时钟称为PLLCLK。倍频因子我们设定为2倍频,也就是说,经过PLL之后,我们的时钟从原来4MHz的 HSE变为8MHz的PLLCLK。

紧接着又遇到了一个开关SW,经过这个开关之后就是STM32的系统时钟(SYSCLK)了。通过这个开关,可以切换SYSCLK的时钟源,可以选择为HSI、PLLCLK、HSE。我们选择为HSI时钟,所以SYSCLK就为8MHz了。

PLLCLK在输入到SW前,还流向了USB预分频器,这个分频器输出为USB外设的时钟(USBCLK),在本例子中我们的USB预分频系数为1.5,此时USBCLK为5.33MHz。

回到SYSCLK,SYSCLK经过AHB预分频器,分频后再输入到其它外设。如输出到称为HCLK、FCLK的时钟,还直接输出到SDIO外设的SDIOCLK时钟、存储器控制器FSMC的FSMCCLK时钟,和作为APB1、APB2的预分频器的输入端。本例子设置AHB预分频器不分频,即输出的频率为8MHz。

GPIO外设是挂载在APB2总线上的, APB2的时钟是APB2预分频器的输出,而APB2预分频器的时钟来源是AHB预分频器。因此,把APB2预分频器设置为不分频,那么我们就可以得到GPIO外设的时钟也等于HCLK,为8MHz了。

APB2的时钟为8MHz,ADC预分频系数为2,所以,ADCCLK为4MHz。

STM32的时钟系统确实是很复杂,不仅有倍频,分频,还有一系列的外设时钟开关。倍频是考虑到了电磁兼容性,如果外部直接提供一个72MHz的晶振,太高的震荡频率会给电路板的制作带来一定的难度。分频则是因为STM32既有高速外设,也有低速外设,各外设的工作频率不相同,需要分开来管理。最后,每个外设时钟还有自己独立的开关(在图上可以看到,在外设时钟之前需要经过一个与门,这就是它们的开关)在我们不使用该外设时,需要把时钟关闭以减少STM32的功耗。

STM32系统时钟默认设置相关推荐

  1. STM32系统时钟设置,采用外部有源晶振相关配置问题

    今天在调试STM32系统时钟设置时遇到一个问题:TIM2定时1Ms,TIM2中断服务函数time++,time=100时LED状态改变.程序运行后发现LED不是按照0.1S的时间闪烁,闪烁的很慢. 查 ...

  2. STM32系统时钟设置(标准库)

    1.STM32F407时钟树 2.系统时钟相关的结构 HSE高速外部时钟信号 锁相环PLL 锁相环的主要作用就是对时钟进行倍频,然后把时钟输出到各个功能部件.PLL有两个,一个主PLL,另一个是专用的 ...

  3. STM32系统时钟及配置方法

    什么是时钟 单片机如果要正常运行,时钟信号是必不可少的.作为CPU的脉搏,时钟的快慢决定了CPU的运行速率,执行指令的速度.一般时钟源会被分频器或倍频器分成多种频率的时钟,以满足系统的不同应用. 那么 ...

  4. STM32系统时钟配置及时钟树

    参考资料:< STM32F4xx 中文参考手册> RCC 章节. STM32时钟可大致分为系统时钟和其它时钟两大类,总共包含5个时钟源 HSI(High Speed Internal Cl ...

  5. STM32F2系列系统时钟默认配置

    新到一家公司后,有个项目要用到STM32F207Vx单片机,找到网上的例子照猫画虎的写了几个例子,比如ADC,可是到了ADC多通道转换的时候就有点傻眼了,这里面的时钟跑的到底是多少M呢?单片机外挂的时 ...

  6. android系统开机默认设置修改记录

    文章目录 1. 前言 2. 默认关闭数据 3. 默认关闭蓝牙 4. 默认关闭定位 5. 默认关闭飞行模式 6. 默认关闭wifi 7. 默认关闭USB调试 8. 默认息屏时间修改 9. 默认亮度修改 ...

  7. STM32系统时钟详解

    STM32时钟树 STM32时钟系统简介 在CPU中时钟系统就像人的心脏一样,给系统一个稳定的类似于人脉搏一样的一个工作时间基准,其重要性是不可言喻的.而STM32F4的时钟系统还是较为复杂的,不像5 ...

  8. STM32f10x晶振及系统时钟频设置

    一.晶振设置 stm32f10x.h文件下HSE_VALUE 注意是下面一个 二.系统时钟配置 system_stm32f10x.c文件下 修改SYSCLK_FREQ_72MHz 值

  9. Android系统语言默认设置为简体中文

       Android系统默认的语言是英语,但是对于中国大陆Android产品厂商来说,不会出厂之后语言还是英语,到用户手里之后,用户自己设置成简体中文吧?有如果客户不懂英语,岂不是就不能设置系统语言了 ...

最新文章

  1. 微信小程序性能优化之一
  2. 2017华南理工华为杯D bx回文
  3. chrome java上传文件_springboot+webuploader 实现大文件切片上传,兼容IE8+,chrome等浏览器,可运行...
  4. SAP Cloud for Customer Account和individual customer的区别
  5. Linux的shell编写
  6. 致命错误: 在类路径或引导类路径中找不到程序包 java.lang_如何提升店铺动态评分 需要提升可以找我...
  7. java 远程监控文件系统_Java 文件系统监控(WatchService)
  8. 论文Attention-guided CNN for image denoising解读
  9. Linux服务器被***不能上网
  10. 脱离标准文档流(1)---浮动
  11. 魔方机器人之下位机编程---------舵机控制
  12. 【火灾检测】基于matlab GUI火灾检测【含Matlab源码 249期】
  13. 从编程角度阐述有限元最佳入门方法:以Abaqus 和OpenSees 为例
  14. java uint,Java如何在java中解析uint8?
  15. github如何写博客
  16. 【开发技术】2万字详细介绍Docker 和 web项目的部署监控,docker部署,拉取kafana,prometheus镜像监控
  17. CSS样式内联选择器选择器优先级伪类顺序
  18. 使用python操作excel的xls文件和xlsx文件之间的批量导出和填充数据
  19. 大数据-玩转数据-hive的安装
  20. OPENCV之人眼检测

热门文章

  1. 一篇文章带你详解 TCP/IP 协议(下)
  2. Java Streams,第 1 部分: java.util.stream 库简介
  3. MYSQL:约束?添加约束?删除约束?以及一些其他修饰?
  4. 22.类对象和类指针
  5. 运行js_最新双十一喵币自动领取方法,安卓手机通过js脚本完美运行
  6. 数据中心暖通相关知识与空调规划设计知识
  7. 生僻字(通信工程版)
  8. java jpopupmenu 无法显示_java – 从JButton显示/隐藏JPopupMenu; FocusListener无法正常工作?...
  9. AI:大力出奇迹?Bigger is better?AI下一代浪潮?—人工智能的大语言模型(LLMs)的简介、发展以及未来趋势
  10. NLP:基于snownlp库对文本实现提取文本关键词和文本摘要