STM32-TIM定时中断(十)

TIM定时中断

第一部分我们主要讲的是定时器基本定时的功能,也就是定一个时间,然后让定时器每隔这个时间产生一个中断,来实现每隔一个固定时间执行一段程序的目的。比如你要做个时钟、秒表,或者使用一些程序算法的时候,都需要用到定时中断的这个功能。

在第二部分我们主要讲的是定时器输出比较的功能。输出比较这个模块最常见的用途就是产生 PWM 波形,用于驱动电机等设备啊。在这个部分我们将会学习到使用 STM32 输出的 PWM 波形来驱动舵机和直流电电机的例子。

在第三部分我们主要讲的是定时器输入捕获的功能。在这部分我们将会学习使用输入捕获这个模块来实现测量方波频率的例子啊。

那在第四部分我们再来学习一下定时器的编码器接口啊。使用这个编码器接口能够更加方便的读取正交编码器的输出波形,在编码电机测速中应用也是非常广泛的。

定时器就是一个计数器啊。当这个计数器的输入是一个准确可靠的基准时钟的时候,那它在对这个基准时钟进行计数的过程,实际上就是计时的过程啊。比如在 STM32 中,定时器的基准时钟一般都是主频 72 兆赫兹啊。比如我对 72 兆赫兹记 72 个数,那就是 1 兆赫兹,也就是 1 微秒的时间啊。如果记 72000 个数,那就是 1000 赫兹啊,也就是 1 毫秒的时间。

32 的定时器拥有 16 位计数器、预分频器、自动重装寄存器的时基单元。在 72 兆赫兹计数时钟下,可以实现最大 59.65 秒的定时。

这里计数器就是用来执行计数定时的一个计数器啊,每来一个时钟计数器加一。

预分频器可以对计数器的时钟进行分频,让这个计数更加灵活啊。

自动重装寄存器就是计数的目标值,就是我想要记多少个时钟申请中断。

这些寄存器构成了定时器最核心的部分,我们把**这一块电路称为时基单元,**这个等会分析定时器结构的时候再详细讲啊。那这个时基单元里面的计数器预分频器自动重装器都是 16 位的,2 的 16 次方是 65536,也就是如果预分频器设置最大,自动重装也设置最大,那定时器的最大定时时间就是 59.65 秒,接近一分钟啊。这个怎么算的呢?就是 72 兆除以 65536,再除 65536,得到的是中断频率,然后取倒数就是 59.65 秒多啊。大家可以自己算一下。这就是最大的定时时间,应该说还是挺长的了。

如果你嫌这个还不够长, STM32 的定时器还支持级联的模式啊,也就是一个定时器的输出当做另一个定时器的输入,这样加一起最大的定时时间就是 59.65 秒再乘两次 65536 这个时间大概是 8000 多年,这下够长了吧?如果还嫌短,那就再级联一个定时器,定时时间还会再延长 65536*65536 倍,这个时间大概是 34 万亿年,这个可见指数爆炸的威力啊。小小的 STM32 三个定时器级联就能实现丈量宇宙年龄的能力。你用 STM32 定个时,就能从宇宙诞生一直记到宇宙灭亡

基本定时器:

首先这一部分有三个最重要的寄存器啊,分别是预分频器、计数器和自动重装寄存器。它们构成了最基本的计数计时电路,所以这一块电路就叫做时基单元。

预分频器之前连接的就是基准计数时钟的输入啊,最终来到了这个位置。由于基本定时器只能选择内部时钟,所以你可以直接认为这根线直接连到了输入端的这里,也就是内部时钟 C K _I N T。内部时钟的来源是 R C C T I M XCLK 这里的频率值一般都是系统的主频 72 兆赫兹。所以通向时基单元的计数基准频率就是 72 兆。

再来看时基单元,首先是预分频器,它可以对这个 72 兆赫兹的计数时钟进行预分频。比如这个计数器写 0,那就是不分频,或者说是一分频,这时候输出频率等于输入频率等于 72 兆赫兹。如果预分频器写一,那就是二分频,输出频率等于输入频率除以二,等于 36 兆赫兹。如果写二,就是三分频,输出等于输入除以3,以此类推。所以预分频器的值和实际的分频系数相差了一,即实际分频系数等于预分频器的值加一。这个预分频器是 16 位的啊,所以最大值可以写 65535,也就是 65536 分频。这就是预分频器,就是对输入的基准频率提前进行一个分频的操作。

然后是计数器,这个计数器可以对预分频后的计数时钟进行计数。计数时钟每来一个上升沿,计数器的值就加一。这个计数器也是 16 位的啊,所以里面的值可以从 0 一直加到 6535。如果再加的话,计数器就会回到 0 重新开始。所以计数器的值在计时过程中会不断的自增运行,当自增运行到目标值时,产生中断,那就完成了定时的任务。所以现在还需要一个存储目标值的计存器,那就是自动重装计存器了。自动重装计存器也是 16 位的,它存的就是我们写入的计数目标,在运行的过程中计数值不断自增,自动重装值是固定的目标。当计数值等于自动重装值时,就是计时时间到了,那它就会产生一个中断信号,并且清零计数器,计数器自动开始下一次的计数计时。

在这里图上画的一个向上的折线箭头啊,就代表这里会产生中断信号。像这种计数值等于自动重装值产生的中断呢,我们一般把它叫做更新中断。这个更新中断之后就会通往 NVIC, 我们再配置好 NVIC 的定时器通道。那定时器的更新中断就能够得到 CPU 的响应了。这里向下的箭头代表的是会产生一个事件,这里对应的事件就叫做更新事件。更新事件不会触发中断,但可以触发内部其他电路的工作。

以上这些就是定时器定时中断的全部流程了。从基准时钟到预分频器,再到计数器,计数器计数自增,同时不断的与自动重装计数器进行比较,它俩值相等时,即计时时间到,这时会产生一个更新中断和更新事件, CPU 响应更新中断,就完成了我们定时中断的任务了。好到这里,定时中断和时基单元的工作流程我们就已经讲完了。

简单的介绍一下这个主模式触发 DAC 的功能吧。 STM32 的一大特色就是这个主从触发模式,它能让内部的硬件在不受程序的控制下实现自动运行。如果能把这个主从触发模式掌握好,那在某些情景下将会极大的减轻 CPU 的负担哈。这个模式我们后面的课程还会再详细讲的,这里简单了解一下。这个主模式触发 DAC 有啥用呢?

这个用途就是在我们使用 DAC 的时候啊,可能会用 DAC 输出一段波形,那就需要每隔一段时间来触发一次 DAC 让它输出下一个电压点。如果用正常的思路来实现的话,就是先设置一个定时器产生中断,每隔一段时间在中断程序中调用代码,手动触发一次 DAC 转换,然后 DAC 输出。这样也是没问题的哈,但是这样会使主程序处于频繁被中断的状态,这会影响主程序的运行和其他中断的响应啊。

所以定时器就设计了一个主模式,使用这个主模式可以把这个定时器的更新事件啊映射到这个触发输出 T R G O 的位置,然后 T R G O 直接接到 DAC 的触发转换引脚上,这样定时器的更新就不需要再通过中断来触发 DAC 转换了,仅需要把更新事件通过主模式映射到 T R G O,然后 T R G O 就会直接去触发 DAC 了,整个过程不需要软件的参与,实现了硬件的自动化啊,这就是主模式的作用。当然除了这个主模式外,还有更多的硬件自动化的设计

通用定时器:

通用定时器这里来,结构就瞬间复杂了很多啊。我们来看一下,首先中间最核心的这一部分还是时基单元,这部分结构和基本定时器是一样的啊,由预分频器计数器自动重装寄存器构成,每部分的工作流程和基本定时器也是一样的。预分频器对时钟进行预分频,计数器自增计数,当计数值达到自动重装值时,计数值清零,同时产生更新中断和更新事件。

不过对于通用定时器而言,这个计数器的计数模式就不止向上计数这一种了。我之前解释的时候都是用的向上计数的模式,也就是计数器从 0 开始向上自增计到重装值,清 0 同时申请中断,然后开始下一轮,依次循环。这是向上计数,除了这种向上计数的模式外,通用定时器和高级定器还支持向下计数模式和中央对齐模式。向下计数模式就是从重装值开始向下自减,减到 0 之后回到重装值同时申请中断,然后继续下一轮,依次循环。这就是向下计数。还有中央对齐的计数模式,就是从零开始先向上自增记到重装值申请中断,然后再向下自减减到 0 再申请中断,然后继续下一轮,依次循环。这是中央对齐模式哈。总结一下就是基本定时器仅支持向上计数这一种模式。通用定时器和高级定时器支持向上计数,向下计数,中央对齐这三种模式。这个模式比较多啊,不过我们最常用的还是向上计数模式啊,所以其他两种模式大家就了解一下,主要掌握向上计数的模式就行了。

然后我们再来看一下上面的这部分结构啊,这些就是内外时钟源选择和主从触发模式的结构了。

我们先看一下内外时钟源选择,对于基本定时器而言,定时器只能选择内部时钟,也就是系统频率 72 兆赫兹。到了通用定时器这里,时钟源不仅可以选择内部的 72 兆赫兹时钟,还可以选择外部时钟。具体都有哪些呢?第一个外部时钟就是来自 TIMx ETR 引脚上的外部时钟。这个 ETR 引脚的位置啊,可以参考一下引脚定义表。可以看到这里有 TIM2 CH1 ETR, 意思就是这个 TIM2 的 CH1 和 ETR 都是复用在了这个位置,也就是 PA0 引脚。下面还有 CH2 CH3 CH4 和其他定时器的一些引脚哈,也都可以在这里找到。

那这里我们可以在这个 TIM2 的 ETR 引脚也就是 PA0 上接一个外部方波时钟,然后配置一下内部的极性选择、边缘检测和预分频器电路,再配置一下输入滤波电路。这些电路可以对外部时钟进行一定的整形啊,因为是外部引脚的时钟,所以难免会有些毛刺,那这些电路就可以对输入的波形进行滤波啊,同时也可以选择一下极性和预分频器。

最后滤波后的信号兵分两路,上面一路 ETRF 进入触发控制器紧跟着就可以选择作为时基单元的时钟了。如果你想在 ETR 外部引脚提供时钟,或者想对 ETR 时钟进行计数,把这个定时器当做计数器来用的话,那就可以配置这一路的电路了。在 STM32 中,这一路也叫做外部时钟模式 2。

除了外部 ETR 引脚可以提供时钟外,下面这里还有一路可以提供时钟,就是 TRGI。 这一路从名字上来看的话,它主要是用作触发输入来使用的哈,这个触发输入可以触发定时器的重模式。关于触发输入和重模式啊,我们后续的课程再讲。本小节我们讲的是这个触发输入作为外部时钟来使用的情况。你暂且可以把这个 TRGI 当做外部时钟的输入来看。当这个 TRGI 当做外部时钟来使用的时候,这一步就叫做外部时钟模式一。那通过这一路的外部时钟都有哪些呢?往左看,第一个就是 ETR 引脚的信号。这里 ETR 引脚既可以通过上面这一路来当做时钟,又可以通过下面这一路来当做时钟。两种情况对于时钟输入而言是等价只不过是下面这一路输入会占用触发输入的通道而已。

然后第二个就是 ITR 信号,这一部分的时钟信号是来自其他定时器的。从右边可以看出啊,这个主模式的输出 TRGO 可以通向其他定时器,那通向其他定时器的时候,就接到了其他定时器的 ITR 引脚上来了。这个 ITR0 到 ITR3 分别来自其他四个定时器的 TRGO 输出。至于具体的连接方式是怎么样的,手册的这个位置有一张表啊

这里可以看到 TIM2 的 ITR0 是接在了 TIM1 的 TRGO 上的, ITR1 接在了 TIM8, ITR2 接在了 TIM3, ITR3 接在了 TIM4。其他定时器也都可以参照一下这个表啊,这就是 ITR 和定时器的连接关系。

通过这一路我们就可以实现定时器级联的功能。比如我们可以先初始化 TIM3,然后使用主模式把它的更新事件映射到 TRGO 上,接着再初始化 TIM2,这里选择 ITR2。对应的就是 TIM3 的 TRGO, 然后后面再选择时钟为外部时钟模式一。这样 TIM3 的更新事件就可以驱动 TIM2 的时基单元,也就实现了定时器的级联。

那我们继续看,这里还可以选择 TIEF 杠 ED, 这里连接的是这里输入捕获单元的 CH1 引脚啊,也就是从 CH1 引脚获得时钟。这里后缀加一个 ED 就是边缘的意思啊,也就是通过这一路输入的时钟,上升沿和下降沿均有效。最后这个时钟还能通过 TIEFP1 和 TIEFP2 获得,其中 TIEFP1 是连记得带这里啊就是 CH1 引脚的时钟啊, TIM2FP2 连接到了这里,就是 CH2 引脚的时钟。

到这里,外部时钟模式一的输入就介绍完了。总结一下就是,外部时钟模式一的输入可以是 ETR 引脚,其他定时器, CH1 引脚的边缘, CH1 引脚。和 CH2 引脚。这还是比较复杂的哈。一般情况下,外部时钟通过 ETR 引脚就可以了。下面设置这么复杂的输入,不仅仅是为了扩大时钟输的范围哈,更多的还是为了某些特殊应用场景而设计的哈。比如为了定时器的级联而设计的这一部分。下面这一部分我们之后讲输入捕获和测频率时还会继续讲的哈,到时候你就会明白它为什么要这样设计了。现在这些电路你大概了解一下就行了哈。

对于时钟输入而言,最常用的还是内部的 72 兆赫兹的时钟。如果要使用外部时钟首选 ETR 引脚外部时钟模式二的输入,这一路最简单最直接哈。那有关时钟输入的部分到这里就讲完了。

这个是定时器的一个编码器接口,可以读取正交编码器的输出波形。这个我们后续课程也会再讲啊。然后接下来右边这里,这个就是定时器的主模式输出了。这部分电路可以把内部的一些事件映射到这个 TRGO 引脚上。比如我们刚才讲基本定时器分析的啊,将更新事件映射到 TRGO 用于触发 DAC。这里也是一样啊,我们可以把定时器内部的一些事件映射到这里来,用于触发发其他定时器 DAC 或者 ADC 可见这个触发输出的范围是比基本定时器更广一些的哈。

我们再看一下下面这部分,这一部分主要包含了两块电路啊,右边这一块是输出比较电路 ,总共有四个通道,分别对应 CH1 到 CH4 的引脚,可以用于输出 PWM 波形,驱动电机啊 。左边这一块是输入捕获电路 ,也是有四个通道,对应的也是 CH1 到 CH4 的引脚,可以用于测量输入方波的频率等啊。中间这个计存器是捕获比较寄存器,是输入捕获和输出比较电路共用的。因为输入捕获和输出比较不能同时使用,所以这里的寄存器是共用的啊,引脚也是共用的。那有关输入捕获和输出比较这部分电路,我们留到之后的视频再具体分析哈。我们本节主要讲的是定时中断和内外时钟源选择,也用不到这部分电路了。

高级定时器:

高级定时器这里,左上的这一大部分都没有变化。

主要改动的就是右边这几个部分,我们来看一下。第一个是这里,申请中断的地方,增加了一个重复次数计数器。有了这个计数器之后,就可以实现每隔几个计数周期才发生一次更新事件和更新中断啊。原来的结构是每个计数周期完成后都会发生更新。现在有个计数器在这里,可以实现每隔几个周期再更新一次,这就相当于对输出的更新信号又做了一次分频哈。那对于高级定时器的话,我们之前计算的最大定时时间 59 秒多,在这里就还需要再乘一个 65536,这就又提升了很多的定时时间了是吧?这就是这个重复计数器的工作流程。

然后下面这里的这些就是高级定时器对输出比较模块的升级了。这些内容简单说一下啊,大家有个印象就行了,现在还不必深入了解。

这个 DTG 是死区生成电路,右边这里的输出引脚由原来的一个变为了两个互补的输出,可以输出一对互补的 PWM 波。这些电路是为了驱动三相无刷电机的哈,三相无刷电机还是比较常用的,比如四轴变频器啊,电动车的后轮啊,电钻等

里面都可能是这个三相无刷电机,因为因为三相无刷发电机的驱动电路一般需要三个桥臂,每个桥臂两个大功率开关管来控制,总共需要六个大功率开关管来控制。所以这里的输出 PWM 引脚的前三路就变为了互补的输出,而第四路却没什么变化啊,因为三相电机只需要三路就行了。

为了防止互补输出的 PWM 驱动桥臂时,在开关切换的瞬间,由于器件的不理想啊,造成短暂的直通现象,所以前面这里就加上了死区生成电路,在开关切换的瞬间产生一定时长的死区,让桥臂的上下管全都关断,防止直通现象啊。

那最后一部分就是刹车输入的功能了。这个是为了给电机驱动提供安全保障的。如果外部引脚 BKIN 产生了刹车信号,或者内部时钟失效产生了故障,那么控制电路就会自动切断电机的输出,防止意外的发生。这就是刹车输入的功能。

要解决两个任务啊,定时中断和内外时钟源选择,这些所涉及的结构。那首先中间最重要的还是, PSC 预分频器, CNT 计数器, ARR 自动重装载寄存器,这三个寄存器构成的实际单元。下面这里是运行控制,就是控制寄存器的一些位啊,比如启动停止啊,向上或向下计数等等。我们操作这些寄存器就能控制实际单元的运行了。

左边是为实际单元提供时钟的部分,这里可以选择 RCC 提供的内部时钟,也可以选择 ETR 引脚提供的外部时钟模式 2。

在本小节示例程序里,第一个定时器定时中断就是用的内部时钟这一路,第二个定时器外部时钟就是用的外部时钟模式 2 这一路。

当然还可以选择这里的触发输入当做外部时钟啊。外部时钟模式一,对应的有 ETR 外部时钟, ITRX 其他定时器, TIX 输入捕获通道。这些就是定时器的所有可选的时钟源了。

最后这里还有个编码器模式,这一般是编码器独用的模式啊,普通的时钟用不到这个。

接下来右边这里就是计时时间到,产生更新中断后的信号去向。在这里,如果是高级定时器的话,还会多一个重复计数器,这个注意一下啊,不过我们暂时就不考虑了。那这里中断信号会先在状态寄存器器里置一个中断标志位,这个标志位也会通过中断输出控制到 NVIC 申请中断。

为什么会有一个中断输出控制呢?因为这个定时器模块有很多地方都要申请中断。比如前面这个图里,不仅更新要申请中断,这里触发信号也会申请中断,还有下面的输入捕获和输出比较匹配时也会申请。

所以这些中断都要经过中断输出控制,如果需要这个中断,那就允许,如果不需要,那就禁止。简单来说,这个中断输出控制就是一个中断输出的允许位。如果需要某个中断,就记得允许一下。

分频器时序图:

好,接下来我们再来看几个时序图啊,研究一下实际单元运行的一些细节问题。

第一个是预分频器时序

这个图是当预分频器的参数从 1 变到 2 时计数器的时序图。第一行是CK_ PSC 预分频器的输入时钟,就是这个图里的这个位置啊。选内部时钟的话一般是 72 兆赫兹。然后这个时钟在不断的运行。

下面这个CNTEN 计数器使能,高电平计数器正常运行,低电平计数器停止。

再下面是 CK_ CNT 计数器时钟。就是这个位置,它既是预分频器的时钟输出,也是计数器的时钟输入啊。

这里可以看到,开始时计数器未使能,计数器始终不运行。然后使能后,前半段预分频器系数为一,计数器的时钟等于预分频器前的时钟。后半段预分频器系数变为二了,计数器的时钟就也变为预分频器前时钟的一半。在计数器时钟的驱动下,下面计数器寄存器也跟随时钟的上升沿不断自增。在中间的这个位置是 FC 之后计数值变为 0 了。这里虽然没写哈,但是可以推断出 ARR 自动重装值就是 FC。当计数值计到和重装值相等,并且下一个时钟来临时,计数值才清零。同时下面这里产生一个更新事件,这就是一个计数周期的工作流程啊。

然后下面还有三行时序,这三行时序是什么意思呢?这里描述的其实是这个预分频计数器的一种缓冲机制啊,也就是这个预分频计数器实际上是有两个,一个是这个,供我们读写用的,它并不直接决定分频系数。另外还有个缓冲计数器,或者说是影子器,缓冲寄存器和影子寄存器啊,这两个说法其实是一个意思啊。这个缓冲寄存器才是真正起作用的寄存器啊。比如我们在某个时刻,把预分频寄存器由 0 改成了 1,如果在此时立刻改变时钟的分频系数啊,那么就会导致这里在一个计数周期内,前半部分和后半部分的频率不一样,这里计数计到一半,计数频率突然就会改变了,这虽然一般并不会有什么问题啊,但是 STM32 的定时器比较严谨,设计了这个缓冲寄存器,这样当我在计数计到一半的时候改变了分频值,这个变化并不会立刻生效,而是会等到本次计数周期结束时产生的更新事件,预分频寄存器的值才会被传递到缓冲寄存器里面去,才会生效啊。

所以在这里看到,即使我在计数中途改变了预分频值,计数频率仍然会保持为原来的频率,直到本轮计数完成,在下一轮计数时,改变后的分频值才会起作用。

最后这里也是啊,预分频器内部实际上也是靠计数来分频的。当预分频值为 0 时,计数器就一直为 0,直接输出原频率。当预分频值为 1 时,计数器就 01010101 这样计数,再回到 0 的时候输出一个脉冲。这样输出频率就是输入频率的二分频。预分频器的值和时间的分频系数之间有一个数的偏移啊

那最下面就有这样一个公式,就是计数器计数频率 CK_ CNT 等于 CK_ PSC 除以 PSC 加一

下一页看一下计数器时序。这个图是计数器时序图,内部时钟分频因子为 2,就是分频系数为 2 啊。第一行是内部时钟 72 兆赫兹,第二行是时钟使能高电平启动,第三行是计数器时钟,因为分频系数为 2,所以这个频率是上面这个除 2 啊。然后计数器在这个时钟每个上升沿自增,当增到 0036 的时候发生溢出,那计到 36 之后再来一个上升沿计数器清零,计数器溢出啊,产生一个更新时件脉冲。另外还会置一个更新中断标志位 UIF, 这个标志位只要置一了,就会去申请中断。然后中断响应后,需要在中断程序中手动清零。这就是计数器的工作流程。

下面有个式子啊,计数器溢出频率 CK_ CNT_ OV 等于 CK_ CNT 除以 ARR 加一。这个 ARR 的值也是要加一的哈。把上面这个式子带进去

就是等于 CK_ PSC 除以 PSC 加一,再除 ARR 加一。这就是我们在计算定时时间的一个式子啊。用 72 兆赫兹除以 PSC 加一,再除 ARR 加一,就能得到溢出频率。如果想算溢出时间,那就只需要取个倒数就行了。

那刚才说了预分频器为了防止计数中途更改数值造成错误啊,设计了缓冲计数器。这个计数器那肯定也少不了这样的设计了,我们可以看一下这个结构图啊,这里面像这样带一个黑色阴影的计数器都是有影子计数器这样的缓冲机制的啊,包括预分频器,自动重装载计数器和下面的捕获比较计数器。所以计数器的这个 ARR 自动重装载计数器也是有一个缓冲计数器的,并且这个缓冲计数器是用还是不用是可以自己设置的。

下面这两个图。第一个计数器无预装时序,就是没有缓冲计数器的情况。第二个有预装时序,就是有缓冲计数器的情况。通过设置这个 ARPE 位,就可以选择是否使用预装功能。我们先看一下无预装的情况,在这里计数器正在进行自增计数,我突然更改了自动加载计数器,就是自动重装计数器啊,由 FF 改成了 36,那计数值的目标值就由 FF 变成了 36,所以这里记到 36 之后就直接更新开始下一轮计数

再看一下下面这个图,有预装的情况。在计数的中途,我突然把计数目标由 F 五改成了三六。可以看到下面有个影子寄存器啊,这个影子寄存器才是真正起作用的,它还是 F 五。所以现在计数的目标还是计到 F 五,产生更新事件。同时要更改的三六才被传递到影子寄存器,在下一个计数周期,这个更改的三六才有效。所以可以看出啊,引入这个影子寄存器的目的实际上是为了同步,就是让值的变化和更新事件同步发生,防止在运行途中更改造成错误啊。

在这个例子也可以看出,如果这里不使用影子计数器的话, F 五改到三六立刻生效,但此时计数值已经到了 F 一,已经超过三六了, F 一只能增加,但它的目标却是三六,比它还小,这样 F 一就只能一直加一直加一直加到 F F F F,再回到 0,再加到三六才能产生更新,这就会造成一些小问题啊。当然如果你不介意这样的问题的啊,那就不用管这些细节了。

毕竟 STM32 设计出来要考虑到各种各样的情况,所以做的比较严谨哈。

RCC时钟树:

在这里给出来了一个 RCC 时钟树的结构图这个时钟树就是 STM32 中用来产生和配置时钟并且把配置好的时钟发送到各个外设的系统啊时钟是所有外设运行的基础所以时钟也是最先需要配置的东西我们之前说过程序中主函数之前还会执行一个 SystemInit函数这个函数就是用来配置这个时钟树的这个结构看上去挺复杂的哈配置起来还是比较麻烦的不过好在 ST 公司已经帮我们写好了配置这个时钟树的 SystemInit的函数啊

那这里我们就来看一下这个时钟树在这个时钟树里啊从这里画一个界限左边的都是时钟的产生电路右边的都是时钟的分配电路 啊中间的这个 System Clock 就是系统时钟 72 兆赫兹,在时钟产生电路啊有四个震荡源分别是内部的 8 兆赫兹高速 RC 振荡器,外部的 4-16 赫兹高速石英晶体振荡器也就是晶振 啊一般都是接 8 兆赫兹,外部的 32.768 千赫兹低速晶振 这个一般是给 RTC 提供时钟的最后是内部的 40 千赫兹低速 RC 振荡器这个可以给看门狗提供时钟,上面这两个高速晶振啊是用来提供系统时钟的我们 AHB APP2 APP1 的时钟都是来源于这两个高速晶振啊,这里内部和外部都有一个 8 兆赫兹的晶振都是可以用的,只不过是外部的石英振荡器比内部的 RC 振荡器更加稳定啊所以一般我们都用外部晶振

但是如果你系统很简单而且不需要那么精确的时钟那也是可以使用内部 RC 振荡器的这样就可以省下外部部晶振的电路啊,那在 SystemInit 函数里 ST 是这样来配置时钟的哈首先它会启动内部时钟选择内部 8 兆赫兹为系统时钟暂时以内部 8 兆赫兹的时钟运行啊,然后再启动外部时钟配置外部时钟走这一路进入 PLL 锁相环进行倍频 8 兆赫兹倍频 9 倍得到 72 兆赫兹等到锁相环输出稳定后选择锁相环输出为系统时钟这样就把系统时钟由 8 兆赫兹切换为 72 兆赫兹这是 ST 配置的流程哈

这样分析之后可以解决实际应用的一个问题哈那就是如果你的外部晶振出问题了可能会导致一个现象哈就是你会发现你程序的时钟慢了大概 10 倍比如你用定时器定一个 1 秒的时间结果过了大概 10 秒才进中断这个问题就出在这里啊如果外部晶振出问题了系统时钟就无法切换到 72 兆赫兹那它就会以内部的 8 兆赫兹运行 8 兆相比于 72 兆大概就慢了 10 倍我之前换了个板子就遇到了这个问题啊我发现时钟好像慢了 10 倍检查一下发现我芯片焊接的时候啊把外部晶振的两个引脚焊短路了最后我把这两个引脚分开时钟就变为正常的 72 兆了

另外这里还有个 CSS 这个是时钟安全系统啊它也是负责切换时钟的,它可以监测外部时钟的运行状态啊一旦外部时钟失效它就会自动把外部时钟切换回内部时钟保证系统时钟的运行啊防止程序卡死造成事故

另外在这个高级定时器这里哈也有这个 CSS 的身影在这个刹车输入这里一旦 CSS 检测到外部时钟失效这里通过或门就会立刻反应到输出比较这里让这个输出控制的电机立刻停止防止意外这就是,这个 STM32 里面的一些安全保障措施

再看一下这右边的时钟分配电路首先系统时钟 72 兆赫兹进入 AHB 总线 AHB 总线有个预分频器在 SystemInit 里配置的分频系数为一,那 AHB 的时钟就是 72 兆赫兹,然后进入 APB1 总线这里配置的分频系数是二,所以 APB1 总线的时钟为 72 兆赫兹除以二等于 36 兆赫兹,现在大家可能会有个问题哈就是我们刚才说通用定时器和基本定时器是接在 APB1 上的,而 APB1 的时钟是 36 兆赫兹按理说它们的时钟应该是 36 兆赫兹啊,但是我在讲定时器的时候一直都说的是所有的定时器的时钟都是 72 兆赫兹这是为啥呢,原因就在这里这下面还有一条支路上面写的是如果 APB1 预分频系数等于一则频率不变否则频率乘二,然后再看右边发现这一路是单独为定时器 2-7 开通的,那因为这里预分频系数我们给的是二,所以这里频率要再乘二,所以通向定时器 2-7 的时钟就又回到了 72 兆赫兹,所以这里就可以有个结论啊无论是高级定时器还是通用定时器还是基本定时器它们的内部基准时钟都是 72 兆赫兹,这个就给我们的使用带来了方便啊不用再考虑不同定时器的时钟不一样的问题了,当然前提是你不乱改它 SystemInit 里面的默认配置,要是改了这里的时钟还得再另行分析,然后我们再看一下下面 APB2 的时钟这里给的分频系数为一所以 APB2 的时钟和 AHB 一样都是 72 兆赫兹这里接在 APB2 上的高级定时器也单开了一路啊,上面写的也是如果 APB2 预分频系数等于一则频率不变,否则频率乘二,但是这里 APB2 的预分频系数就是一,所以频率不变,定时器一和八的时钟就是 72 兆赫兹啊

那在这些时钟输出这里啊都有一个与门进行输出控制控制位写的是外部时钟使能,这就是我们在程序中写 RCC APB2 或者 APB1 外设时钟控制作用的地方,打开时钟就是在这个位置写一让左边的时钟能够通过与门输出给外设

那有关时钟树的内容我就讲到这里啊剩下的还有一些给 ADC 啊 SDIO 等等这些提供时钟的电路啊

相关推荐
普中科技1 小时前
【普中 51-Ai8051 开发攻略】-- 第 24 章 RTC 时钟实验
单片机·嵌入式硬件·rtc·实时时钟·普中科技·ai8051u·aicube
-liming-2 小时前
单片机设计_串口调试工具
数据库·单片机·mongodb
潜创微科技3 小时前
IT9201+IT66021:便携 KVM 一站式方案,音视控三合一免驱即插即用
嵌入式硬件·音视频
CHANG_THE_WORLD3 小时前
PE文件二进制对比
stm32·单片机·嵌入式硬件
西城微科方案开发5 小时前
华润微CS98P370D2L:高性价比低功耗8位MCU
单片机·嵌入式硬件
时光の尘6 小时前
【嵌入式大厂面经】·CAN总线常见考点(持续更新中···)
stm32·单片机·mcu·物联网·can·ack
小叮当⇔6 小时前
系统认为 “从网络 / AI 生成的文件” 不安全,禁止预览但允许手动打开
嵌入式硬件
国科安芯7 小时前
空间辐射环境下电机伺服系统的抗扰动控制:AS32S601 抗辐射 MCU 在航天机电执行机构中的多场景应用与可靠性评估
单片机·嵌入式硬件·mcu·cocos2d·risc-v
国科安芯8 小时前
AS32S601 抗辐射 MCU 在星载高速光通信链路的集成设计与性能验证
网络·单片机·嵌入式硬件·risc-v·安全性测试