前言
本次我们认识一下STM32F103的时钟树架构,以及系统时钟在内部的初始化是怎么处理的,大部分是自己收集和整理,如有侵权请联系我删除。
交流群:717237739
如果觉得有用点赞关注收藏三连,多谢支持
本博客内容原创,创作不易,转载请注明
1.初步认识时钟树(HSI,HSE,LSI,LSE,PLL)
在 STM32 中,有五个时钟源,为 HSI、HSE、LSI、LSE、PLL。从时钟频率来分可以分为 高速时钟源和低速时钟源,在这 5 个中 HIS,HSE 以及 PLL 是高速时钟,LSI 和 LSE 是低速时 钟。从来源可分为外部时钟源和内部时钟源,外部时钟源就是从外部通过接晶振的方式获取时 钟源,其中 HSE 和 LSE 是外部时钟源,其他的是内部时钟源。
HSI振荡器时钟(高速内部时钟)--- 频率为 8MHz
产生的频率精度不是很高,一般使用内部晶振 |
当HSI被用于作为PLL时钟的输入时,系统时钟能得到的最大频率是64MHz。 |
HSI时钟信号由内部8MHz的RC振荡器产生,可直接作为系统时钟或在2分频后作为PLL输入 |
时钟控制寄存器中的HSIRDY位用来指示HSI RC振荡器是否稳定。 |
在时钟启动过程中,直到这一位被硬件置’1’,HSI RC输出时钟才被释放。HSI RC可由时钟控制寄存器中的HSION位来启动和关闭。 |
HSE振荡器时钟(高速外部时钟)
在这个模式里,必须提供外部时钟。它的频率最高可达25MHz。(F1为8M,F4为25M) |
可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。 |
在时钟控制寄存器RCC_CR中的HSERDY位用来指示高速外部振荡器是否稳定。 |
LSE低速外部时钟 --- 频率为 32.768kHz 的石英晶体
40kHz低速内部RC,可以用于驱动独立看门狗和通过程序选择驱动RTC。 |
LSE晶体是一个32.768kHz的低速外部晶体或陶瓷谐振器。它为实时时钟或者其他定时功能提供一个低功耗且精确的时钟源。 |
LSE晶体通过在备份域控制寄存器(RCC_BDCR)里的LSEON位启动和关闭。 |
LSI低速内部时钟
LSI RC担当一个低功耗时钟源的角色,它可以在停机和待机模式下保持运行,为独立看门狗和自动唤醒单元提供时钟。 |
LSI时钟频率大约40kHz(在30kHz和60kHz之间)。 |
LSI RC可以通过控制/状态寄存器(RCC_CSR)里的LSION位来启动或关闭。 |
LSI校准 --- 只有大容量和互联型产品可以进行LSI校准
可以通过校准内部低速振荡器LSI来补偿其频率偏移,从而获得精度可接受的RTC时间基数,以 及独立看门狗(IWDG)的超时时间(当这些外设以LSI为时钟源)。 校准可以通过使用TIM5的输入时钟(TIM5_CLK)测量LSI时钟频率实现。测量以HSE的精度为保 证,软件可以通过调整RTC的20位预分频器来获得精确的RTC时钟基数,以及通过计算得到精 确的独立看门狗(IWDG)的超时时间。
小结:通过对上面的五个时钟源的介绍和说明,相信大家对于ST芯片内部的时钟有了大概的了解,但是对于这些了解,我们并不知道了解的作用在哪里。
下面我们继续说明,讲一下这些时钟在内部是怎么实现的
很多人都以为函数的执行是从main函数实现的,其实这种说法也是可以的,但是在一定程度上来说,程序的执行都需要先运行启动文件,就相当于你电脑开机的等待一样,我们单片机的运行也是从启动文件开始的,确定好相应的时钟配置后,我们才会执行到main函数。
2. 系统初始化函数
建议大家在看这个流程的时候,最好打开自己的工程一步一步看下去,我这的图片放的有限。
从启动文件开始,调用了系统初始化函数(SystemInit)和main函数
1)复位RCC时钟
2)开启内部高速时钟--HSE
很多小伙伴可能还没有学过寄存器说明,后面我会在C专栏写一个博客,目前我们首先打开HSE时钟,时钟开启的时候都需要复位(图片绿色部分英文说明),而在前面的时候我们已经看到RCC已经复位了。
这个函数意思是在RCC的CR寄存器里面,在第0位置1,下面我们看看寄存器第0位为1代表什么:
代表了开启HSI的时钟;
3)关闭了 HSEON, CSSON and PLLON - - - 0xFEF6FFFF
这里我们可以通过位运算来看,因为芯片是32位的,所以0xFEF6FFFF的二进制位为:
1111 1110 1111 0110 1111 1111 1111 1111 可以看到是第16,19,24位清0
4)复位了Reset HSEBYP - - - 0xFFFBFFFF(第18位清0--1011)
5)复位了Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE - - - 0xFF80FFFF
这个时候也有人有疑问了,既然我们要使用,为什么要打开,又要关闭,到底应该配置哪些时钟芯片才能驱动?
其他时钟介绍:
1)PLL时钟源
PLL时钟来源可以有两个:一个是HSE,另一个是HSI/2。由时钟配置寄存器CFGR的位16,即PLLSRC设置具体用哪个。HSI是内部高速的时钟信号,频率为8MHz,这里我们选择HSE作为PLL的时钟来源。
2)PLL时钟PLLCLK
通过设置PLL的倍频因子,可以对PLL的时钟来源进行倍频,倍频因子可以是2至16,由时钟配置寄存器CFGR的位21~18,即PLLMUL[3:0]设置,这里设置为9倍频,因为上一步设置PLL的时钟来源为HSE=8MHz,所以PLLCLK=8M*9=72M。72M是ST官方推荐的稳定运行时钟,可以增大倍频因子实现超频,最大为128MHz。
3)系统时钟SYSCLK
由图可知系统时钟的来源可以是HSI,PLLCLK,HSE,具体由时钟配置寄存器CFGR的为1~0,即SW[1:0]设置。这里设置系统时钟:SYSCLK=PLLCLK=72MHz。
①、AHB 总线、内核、内存和 DMA 使用的 HCLK 时钟。
②、通过 8 分频后送给 Cortex 的系统定时器时钟,也就是 systick 了。
③、直接送给 Cortex 的空闲运行时钟 FCLK。
④、送给 APB1 分频器。APB1 分频器输出一路供 APB1 外设使用(PCLK1,最大 频率 36MHz),另一路送给定时器(Timer)2、3、4 倍频器使用。
⑤、送给 APB2 分频器。APB2 分频器分频输出一路供 APB2 外设使用(PCLK2, 最大频率 72MHz),另一路送给定时器(Timer)1 倍频器使用。
4)AHB总线时钟HCLK
系统时钟SYSCLK经过AHB预分频器分频之后得到的时钟叫APB总线时钟,即HCLK,分频因子可以是[1,2,4,8,16,64,128,256,512],具体由时钟配置寄存器CFGR的位7~4,即HPRE[3:0]设置。这里设置为1分频,即HCLK=SYSCLK=72MHz。
5)APB1总线时钟HCLK1
APB1总线时钟PCLK1由HCLK经过低速APB2预分频器得到,分频因子可以是[1,2,4,8,16],具体由时钟配置寄存器CFGR的位10~8,即PRRE1[2:0]设置。HCLK1属于低速的总线时钟,最高为36MHz。片上低速外设就挂载到这条总线上,比如USART2/3/4/5,SPI2/3,IIC1/IIC2等。这里设置2分频,即PCLK1=HCLK/2=36MHz。
包括电源接口、 备份接口、CAN、USB、I2C1、I2C2、UART2、UART3 等等
6)APB2总线时钟HCLK2
APB2总线时钟PCLK2由HCLK经过高速APB2预分频器得到,分频因子可以是[1,2,4,8,16],具体由时钟配置寄存器CFGR的位13~11,即PPRE2[2:0]设置。HCLK2属于高速的总线时钟,片上高速外设就挂载到这条总线上,比如全部GPIO,USART1,SPI1等。这里设置1分频,即PCLK2=HCLK=72MHz。
高速外设包 括 UART1、SPI1、Timer1、ADC1、ADC2、所有普通 IO 口(PA~PE)、第二功能 IO 口等。
3.调用了设置系统时钟函数
对于系统时钟,默认情况 下是在 SystemInit 函数的 SetSysClock()函数中间判断的,而设置是通过宏定义设置的。
STM32 时钟系统的配置除了初始化的时候在 system_stm32f10x.c 中的 SystemInit()函数中 外,其他的配置主要在 stm32f10x_rcc.c 文件中,里面有很多时钟设置函数,大家可以打开这个 文件浏览一下,基本上看看函数的名称就知道这个函数的作用。
经过上面的时钟配置后,现在才开始进入我们需要的时钟配置选择,我们点击这个函数,F12跳转过去看看说明:
当我们设置好系统时钟后,可以通过变量 SystemCoreClock 获取系统时钟 值,如果系统是 72M 时钟,那么 SystemCoreClock=72000000。这是在 system_stm32f10x.c 文件中设置的,
因为我们的芯片系统时钟频率默认为72M,所以我们直接跳转到这个72M的函数里面看看别人是怎么帮我们配置好时钟的。
1)等待HSE启动,晶振启动需要一定的时间,如果超时则进入中断
系统时钟 SYSCLK,它是供 STM32 中绝大部分部件工作的时 钟源。系统时钟可选择为 PLL 输出、HSI 或者 HSE。系统时钟最大频率为 72MHz, 当然你也可以超频,不过一般情况为了系统稳定性是没有必要冒风险去超频的。
因为HSE是外部高速时钟,所以一般来时我们首先应该先驱动外部晶振,如果启动不成功,则表明外部晶振虚焊或者没有,这个时候我们系统则会选择用内部时钟驱动,但是内部晶振不稳定,所以一般出现芯片无法使用,也可以检查一下外部晶振。
里面的寄存器说明和定义我就不一一举例了,因为定义实在太多了,经过上面的说明大家应该对寄存器怎么赋值应该了解了,我们在例程里面直接跳转过去看定义了解。
2)设置AHB时钟等于系统时钟,设置APB2的时钟不分频
3)设置APB1的时钟为2分频 - - APB1的时钟为36M
4)配置主PLL时钟为系统时钟72M
因为 USB 的时钟是来自 PLL 时钟源。STM32 中有一个全速功能 的 USB 模块,其串行接口引擎需要一个频率为 48MHz 的时钟源。该时钟源只能 从 PLL 输出端获取,可以选择为 1.5 分频或者 1 分频,也就是,当需要使用 USB 模块时,PLL 必须使能,并且时钟频率配置为 48MHz 或 72MHz。
5)打开PLL时钟
总结:
经过上面的步骤,我们初步认识了时钟树和时钟的配置流程,不过一般来说这些并不需要我们配置,但是我们也要了解为什么要这样配置才能使用,毕竟有的时候我们移植或者用其他芯片的时候,可能也会需要改动时钟树的内容。
交流群:717237739
如果觉得有用点赞关注收藏三连,多谢支持
本博客内容原创,创作不易,转载请注明
点赞关注双击博主,不定期分享单片机知识,互相学习交流。