今天我们来学习一下时钟,时钟是单片机运行的基础,任何的外设都需要使能相应的外设时钟才能正常工作,在前面的两章中我们都只是粗略的配置了一下时钟树。今天我们要具体分析一下时钟系统框图,掌握时钟的相关概念以及学习一下定时器这一个外设。
基本概念
上图中一个方波成为一个周期,之前我们也谈过,对于方形脉冲,电平从低电平到高电平的那条竖线称为上升沿,反之从高电平到低电平的称为下降沿,时钟信号就是这样一个特殊的方波脉冲,
或者叫时钟脉冲。
-
脉冲周期:两个脉冲相继出现的时间,脉冲周期是频率的倒数
-
(脉冲)频率:单位时间内(1秒)所产生的脉冲个数,频率的单位有 GHz=1000MHz =1000kHz=1000Hz
-
时钟源:产生时钟脉冲的源头,可以是外部晶振/陶瓷谐振器、RC振荡器等
-
倍频:一种增大频率的方法,使输出频率是输入频率的整数倍
-
分频:一种减小频率的方法,使输出频率是输入频率的整数倍分之一
时钟——单片机的心脏
像人的生命活动需要心脏的跳动一样,单片机的各部分执行指令也需要一个“心脏”,而这个”心脏“就是我们的时钟。任何外设的使用都需要使能其外设时钟。实际上即使我们不配置时钟树直接生成代码,我们会发现在Startup_stm32f427xx.s启动文件中,早已经有用汇编写的代码来初始化系统时钟。
可以看出,在即使是STM32CubeMX生成的代码中,RCC时钟也是第一个使能的。其中RCC外设的全称是Reset clock control,即复位和时钟控制,这里主要是时钟部分的控制,接下来我们再谈谈为什么没有时钟,单片机就无法正常工作。
在第一篇文章中我们说到,我们对单片机的控制,最底层的控制,就是对寄存器进行读写。这里在嵌入式中寄存器更偏重于两种功能:读和写。当读取一个寄存器时,可以把寄存器看作一个只能装0或者1的抽屉,你打开抽屉看到的0或者1反应了单片机内部的一些工作状态,或是有一组寄存器,单片机将一些数据通过二进制编码把数据依次存入寄存器中,这时每个寄存器的0或者1就相当于数据某一位的0或者1。当对一个寄存器进行写操作时,我们可以把一个寄存器置位(写入1)或者复位(写入0),这时寄存器更像一个开关,我们可以通过写1或者0来开启/关闭某个功能,CPU也可以进行同样的读写操作。
那现在情况来了,外设产生了一个请求将寄存器A置位,假如CPU需要根据从寄存器A中读取的0/1来决定是否对寄存器B写1。CPU读寄存器A是1也就是高电平,他将寄存器B置位。那CPU下次执行该操作时,他读取到的寄存器A的高电平,他怎么判断这是上一次的请求还是产生新的请求?
这时候就需要一个全局的时钟信号来同步整个电路,时钟信号给数字系统中每一个时序逻辑一个开始工作的时间点。再打个比方,时钟信号就好比学生跑操时喊的“121212”的口令,所有的人(元器件)都是按照这个口令来迈左右脚的(工作),口令喊的越快,整个队伍也就跑的越快,那是不是时钟信号的频率要越高越好呢?其实不然,当口令快到超过人抬放脚的频率时,就好比有一个人跟不上口令就会绊倒其他人导致一些人都不能跟上队伍一样,电子元件也是有反应速度的,如果写入数据的速度跟不上时钟的变化速度,就会出现还未写完数据时钟信号就已经跳变无法写入的情况。
所以,每一个外设在使能时都需要先使能其对应的外设时钟,否则寄存器就无法正常读写,自然外设也就无法正常工作。而且我们时钟频率也有一定的要求,频率既不能太快也不能太慢,只有合适的频率单片机才能正常且高效地工作。
-
时钟频率过低:不能满足设备的频率需求,可能会无法启动设备。
-
时钟频率在允许范围内频率越快,外设工作效率越高
-
时钟频率过高:功耗越大,造成浪费,同时电路的抗电磁干扰能力越弱,系统稳定性受影响
不同的外设对时钟频率的需求也不一样,为了兼容不同速度的设备,有些高速,有些低速。MCU通常是采用多时钟源的方法来解决这些问题,从而衍生出了时钟系统和时钟树
时钟树与时钟系统
上图是STM32F4xx的时钟系统框图,在这里你可以看到所有的外设时钟的来源,可能你会很疑惑,你没有看到之前学过的像GPIO、EXTI等你熟悉的外设。先不用着急,等我分析完后你就能自己找到所有的外设时钟,为了更好地与实操相结合,我们以STM32CubeMX中的时钟树配置框图来讲解时钟树系统。
我将STM32CubeMX中的时钟树图缩小到可以截下全景,和上面的时钟系统框图对比后可以发现基本没有差别,而我们重点要学习的就是红框中的时钟配置,因为核心功能和外设的配置都在里面,未框选的部分都是一些独立的、使用频率较低的外设,但是不代表这个外设不重要,比如RTC时钟,像这些外设在你看完这篇文章后也会自己分析其时钟的来源和配置。在学习时钟树时,我们要重点把握以下3点:
-
时钟源
-
分/倍频处理
-
输出到什么外设
将时钟图放大后,我们来分析一下stm32的四个时钟源
如图所示,STM32主要有内部时钟和外部时钟,其中每种时钟都有高速与低速之分,所以有4种时钟源
HSE 高速外部时钟信号
HSE: High Speed External Clock signal 即高速外部时钟信号
在图中可以看出HSE是由两个引脚输入时钟信号(OSC_IN引脚和OSC_OUT引脚),输入的信号频率范围是4~25MHz
HSE的输入信号来源又分为两种:
-
外部(旁路)时钟源 BYPASS clock source
-
外部晶振/陶瓷谐振器 Crystal/Ceramic Resonator
当使用旁路时钟源时,OSC_OUT脚悬空处于高阻态,时钟源仅由OSC_IN脚输入,时钟信号占空比约为50%
当使用外部晶振/陶瓷谐振器时,电路中要搭配两个谐振电容,时钟信号由两个脚(OSC_IN 和OSC_OUT)引入。
这些都能在STM32CubeMX中配置
HSE的频率非常高,基本上是四个时钟源中最高的一个,并且HSE的精度高,不容易受温度影响,所以是使用最多的时钟源。
在A型板的原理图中我们可以看到晶振的频率是12MHz,所以我们在CubeMX的Input frequency中填12
HSI 高速内部时钟信号
HSI High Speed Internal Clock signal 即高速外部时钟信号
HSI内部高速时钟的时钟来源是内部 16 MHz RC 振荡器, 虽说16MHz比HSE的外部高速时钟频率高,启动速度也比HSE快,但是精度比不上HSE,HSI的时钟信号受温度影响特别大,有温漂现象。所以HSI常作为备用时钟,当HSE出现故障时,有中断将HSI作为时钟输入让系统恢复正常使用。但这只是权宜之计,并非万全之策,最好的方法还是要采取相应的补救措施并报警,然后修复 HSE。临时使用 HSI 只是为了把损失降低到最小,毕竟 HSI 较于 HSE 精度还是要低。
LSE 低速外部时钟信号
Low Speed External Clock Signal 低速外部时钟信号
与HSE一样,LSE同样有两个时钟源: 旁路时钟源和外部晶振/陶瓷振荡器时钟源。参考HSE即可。但是与HSE相比,LSE的晶振频率就小了很多,LSE 晶振是 32.768 kHz 低速外部 (LSE) 晶振或陶瓷谐振器 。仅仅32.768kHz注意单位是kHz。从图中可以看出,LSE的主要作用于RTC时钟来提供时钟和日历等其他定时功能,具有功耗低和j精度高的特点。RTC时钟也叫实时时钟(Real Time Clock)和我们日常生活中的钟表功能一样,主要提供秒分时、星期、月份、年份等日历功能,这里只做了解。
LSI 低速内部时钟信号
Low Speed Internal Clock Signal 低速内部时钟信号
LSI和HSI一样是由RC振荡电路产生时钟脉冲,时钟频率是32kHz,可作为低功耗时钟源在停机和待机模式下保持运行,供独立看门狗 (IWDG) 和自动唤醒单元 (AWU) 使用。
说到这里四种时钟源就已经全部介绍完毕了,概括地说内部时钟是在芯片内部RC振荡器产生的,起振较快,所以时钟在芯片刚上电的时候,默认使用内部高速时钟。而外部时钟信号是由外部的晶振输入的,在精度和稳定性上都有很大优势,所以上电之后我们再通过软件配置,转而采用外部时钟信号。
PLL时钟
PLL(Phase Locked Loop),中文叫做锁相环或是锁相回路,经过锁相环输出的信号称为锁相环时钟信号
PLL 的主要作用是对时钟进行倍频 再进行输出。STM32F4xx的系统时钟(SYSCLK)官方推荐的最高稳定时钟可以达到180MHz频率(当然可以超频,但是不推荐),这18Mhz由晶振是很难实现的,所以需要经过一个倍频器来放大,PLL就是这样一个倍频电路。PLL有两个:一个是主PLL( Main PLL),另一个是I2S专用的PLLI2S。现在我们来分析一下主PLL时钟。
首先是PLL时钟的输入,1处的梯形是PLL时钟源选择器(PLL Source Mux),他可以选择输入PLL电路的时钟源是哪个。这里PLL时钟的输入时钟源只有HSE和HSI,输入之后信号经过M分频因子(2处)分频,输入到PLL内部的一个叫VCO的亚控振荡器内。
这个VCO可以产生高频信号,VCO对输入和输出信号频率都有要求:输入VCO的信号频率必须在1~2MHz之间,所以有M分频因子将HSE或者HSI信号分频后输入;VCO输出的高频信号又必须在193到432之间,所以会有N倍频因子(3处)将信号倍频作为VCO的输出。STM32F427中,VCO的输出有两个分频因子(不要忘了系统时钟最高是180MHz):分频因子P可以对信号进行2、4、6、8分频之后可以作为系统时钟的输入;分配因子Q取值从4 ~15 不等,分频后作为 USB OTG FS的时钟。
这里有个很有意思的事情, USB OTG FS的时钟频率必须是使用48MHz,但是如果我们想要系统时钟达到官方推荐的180MHz,那么VCO的输出在 经过分频因子P之前的时钟频率是360Mhz,而360MHz/48MHz=7.5,也就是说如果要360MHz分频成48MHz得7.5分频,而分频因子必须是整数。所以48MHz的USB OTG FS时钟和180MHz的系统时钟不可兼得,要想使用USB功能,常常退而求其次,将系统时钟配置成168MHz。这也就是为什么HCLK的下面写着180MHz MAX而我们经常配置成168MHz的原因。
网上有许多说法说STM32有5个时钟源:HSE、HSI、LSE、LSI、PLL。但是通过上面的分析我们可以看出,PLL时钟其实不算一个独立的时钟源,PLL时钟源的输入是HSE或者HSI,PLL本身只是起到一个倍频的作用,不能独立输出时钟信号。
SYSCLK 系统时钟
System Clock 系统时钟
系统时钟的时钟源输入由System Clock Mux选择,有HSE、HSI、PLL三个输入,但是要想达到25MHz以上的频率,只能由PLL作为时钟源输入,此外还可以配置CSS,即时钟监视系统。当使能CSS 使能后,如果 HSE 时钟偶发故障失效时, CSS 将生成一个中断,进而促使 NMI 自动生成 。NMI即上一篇文章中说到的Non Maskable Interrupt,不可屏蔽中断。该中断的优先级相当高,是负数,而且CPU不可屏蔽。在进入NMI中断后,系统时钟会禁止HSE并使能HSI作为紧急抢救,保护系统正常工作。
系统时钟是供STM32中绝大部分部件工作的时钟源。除了直接作为以太网PTP时钟源外,系统时钟都经过了AHB预分频器(AHB Prescaler)后输送给5大模块。但是我们通常都是AHBPrescaler设置成1分频也就是不分频,像HCLK和FCLK时钟的频率都是系统时钟的频率。这一块STM32CubeMX的时钟树和STM32F4XX中文参考手册时钟树有出入,为了准确性我还是选择用STM32F4xx中文参考手册。
系统时钟(SYSCLK)信号经过AHB预分频器后主要有5个去向。
-
HCLK:中文叫AHB总线时钟、频率和SYSCLK一样,将时钟信号提供给存储器,DMA及cortex内核,我们说的MCU主频一般指HCLK的频率,他频率的高低决定了执行代码速度的快慢
-
八分频后输送到系统定时器(Systick)
-
FCLK: Free run clock *运行时钟,*表示FCLK并不来源于HCLK,所以HCLK停止时FCLK也正常运行,FCLK和HCLK信号互相同步,在休眠模式下通过FCLK依旧可以采样到中断和跟踪休眠事件
-
经过APB1分频器分频后直接供给APB1总线外设,或是再倍频给挂载在APB1总线上的定时器,APB1总线时钟(PCLK1)频率最高是45MHz
-
经过APB2分频器分频后直接供给APB2总线外设,或是再倍频给挂载在APB2总线上的定时器,APB2总线时钟(PCLK2)频率最高是90MHz
再来说说总线(BUS)的概念:外设与外设、外设与内核之间要进行数据、指令交换,但是外设的数量非常庞大,如果全部一一对应建立数据通道的话非常麻烦,所以有了总线这一种特殊布线方式,总线可以理解成一辆数据公交车(也就是BUS),公交车会历遍全部站点,所有的外设或者内核都能将数据送上”BUS“,“到站的数据”也能下车到对应的外设。
那这里出现了2条总线:
-
AHB总线:(Advanced High performance Bus),高性能总线,是一种系统总线,它主要负责连接处理器、DMA等一些内部接口。
-
APB总线:(Advanced Peripheral Bus),片上外设总线,它主要负责连接外围设备,它又分为APB1和APB2。
上图是STM32F427和F429的总线架构图,可以看到芯片内部的一些片上外设如DMA、GPIO等是挂载在AHB总线上,APB2上挂载的是一些高速外设如TIM1,TIM8,USART1、ADC等,时钟频率比较低的外设就挂载在APB1上,如TIM2~5 、UART4等等。这些都可以在芯片资料表里面查阅到。
至此,系统时钟的时钟信号走向都介绍完了,可以看到,系统时钟(SYSCLK)是非常重要的,这也是为什么HSE作为系统时钟的输入时钟源时会有CSS时钟监视系统来保证SYSCLK一直有时钟信号输入,SYSCLK下游的HCLK(AHB总线时钟)、FCLK(*运行时钟)SysTick(系统定时器)、PCLK1(APB1总线时钟)、PCLK2(APB2总线时钟)几乎涵盖了我们日常使用的全部外设,所以掌握这些时钟的配置,对我们能够正常使用外设具有很重要的意义。
至于为什么要有那么多的时钟源,意义有两个:
-
兼容不同工作频率的外设,避免功耗过大造成资源浪费
-
多个时钟源可以防止出现单一时钟故障而整体工作瘫痪的问题
总结
通过本篇文章的学习,我们需要重点掌握以下内容
-
时钟频率的概念
-
为什么使用外设需要先使能外设时钟?
-
时钟树时钟信号3要点: 时钟源是什么?、哪些分/倍频处理?、时钟信号输出流向哪?
-