本次编写的教程主要是针对 STM32 F04x系列的 单片机 ,对于STM32单片机的 时钟 ,想必使用过STM32的人都比较清楚,STM32它是基于 Cor te x®-Mx系列内核的微处理器,芯片内部集成了丰富的外设。同时也集成了内部的时钟源。也就是说芯片不需要外接晶振就可以运行。但是大多数的使用情况都是使用了芯片外部的晶振,包括官方的标准固件库也都是默认使用外部晶振,但是有些特殊情况下,不需要使用外部晶振,这样可以节省一个晶振和两个谐振 电容 ,最主要的是可以节省 PCB板 子的面积。但如果使用内部晶振,就得要编写程序,更改相关 寄存器 的值,切换至内部晶振才可以。对于芯片时钟源切换这样的事情,对高手来说是很简单,对于新手来说就有些搞不清了,因此本教程叙述一下STM32F04x系列单片机时钟源切换的流程。
既然是切换单片机的时钟源,就不能不了解下芯片内部的时钟结构,几乎所有的STM32芯片,官方在手册中都会描述一下芯片内部的时钟结构。STM32F04x也不列外,下面是STM32F04x系列单片机的时钟树:(摘自官方手册)
图中序号说明:
①:外部时钟源的输入端。这个时钟源是系统时钟,可用的时钟源频率范围是(4~32)MHz。
②:外部 实时时钟 的时钟源输入端。这个时钟源是计时使用,所以它的频率是固定在32.768KHz。
③:芯片内部时钟输出端。可以控制相关的寄存器,选择内部的时钟信号从这个端口对外输出。
④:内部高速48MHz的时钟源。该频率不需要倍频就可以直接给芯片的提供48MHz的系统时钟信号。
⑤:内部低速8MHz的时钟源。该频率可以倍频或不倍频给系统提供时钟信号。(但是STM32F04x芯片最高频率是48MHz)
⑥:PLL倍频模块。该模块可以选择内部8M或外部时钟为输入,经倍频后给芯片系统提供时钟信号。
⑦:SW系统时钟源选择器。通过控制寄存器来选择相关的时钟源为芯片系统使用。
本次要切换的时钟源是①HSE外部时钟源和⑤内部8M时钟源。不知大家是否留意过,市面上出售的各种STM32的开发板其外部的时钟基本都是8MHz的,这是为什么呢?主要原因是让初学者更快的上手。大家可以结合上图的时钟树和官方的固件库就可以得知,芯片内部的时钟源频率是8MHz,而官方的固件库中配置系统时钟源的时候,定义的相关变量和函数等,也都是用8MHz为基础进行定义的。这样一来,初学者就可以暂时不需要很清楚的了解时钟结构的情况下,快速进行开发。节省了很多的时间,同时也降低了上手的难度。如果一开始就让初学者要清楚的去了解芯片的时钟结构,这样对于能力强的人是无所谓的。但是对新手来说不是一个好的开始,也有可能会打击学习的信心。
看完芯片的时钟树后,在看看官方的固件库是怎么实现系统时钟信号的配置:
STM32的芯片在启动的时候,都是先从启动文件开始执行的,而上图中的程序就是在启动文件中调用的,从上面的程序中可以看出,芯片在启动的时候使用了(默认)内部的8MHz时钟。之后是清除与时钟相关的一切设置,最后调用了一个系统时钟设置函数,该函数的源代码如下:
上图的函数就是在芯片复位完与时钟相关寄存器后,进行配置系统时钟源时调用的函数,该函数主要是进行了五个操作,分别是①启用外部时钟源,②设置PLL的输入时钟源于PLL的倍频系数,③设置FLASH预取指与延迟周期,④设置系统时钟分频系数和外设总线时钟分频系数,⑤设置PLL模块输出频率为系统时钟源。这是官方默认的设置,从这里就可以看出,如果外部使用了8MHz的晶振时,PLL模块倍频6倍。则系统的时钟频率是8*6=48MHz。如果我们不想使用外部的晶振,则只能在这里进行编程设置相关寄存器的数值,达到我们的目的。具体的程序如下:
上图是程序的设置过程是:
①开启内部8MHz时钟(这一步也可以不写,因为芯片上电后默认开启了内部8MHz时钟)。
②等待内部时钟稳定。
③配置FLASH预取指与等待周期。
④设置HPRE与PPRE的分频系数。(一般情况下这两个总线是不分频的,除非对功耗有要求则需要分频)
⑤设置PLL的输入源和PLL模块的倍频系数。
(在设置PLL模块时,必须先清除对该模块的相关设置位,因为只有在PLL模块关闭的情况下才能写入相关的控制信息)
⑥等待PLL模块输出稳定。
⑦设置PLL模块为系统时钟。
⑧等待设置PLL模块为系统时钟完成。
按照上述过程配置完相关寄存器后,芯片的系统时钟就设置为内部的8MHz。经过PLL模块倍频*6后,系统的最高频率是8*6=48MHz。
在配置芯片的内部时钟时,要注意的是:官方的固件库中默认是使用外部晶振,并在时钟配置函数SetSysClock中进行了外部时钟稳定等待,假如外部时钟启动失败的时候,默认是没有相关函数去处理。所以,如果你的 PCB 板子上并没有焊接外部的晶振时,切换时钟的函数就写在官方固件库system_stm32f0xx文件中的SetSysClock函数中,这样一来启动过程中就直接将内部时钟初始化为芯片的系统时钟。