石英晶体振荡器(简称“晶振”)是一种具有高精度和高稳定度的振荡器。石英晶片之所以能作为振荡电路(谐振),是因为它的压电效应。当在晶振极板间施加交变电压时,迫使晶振产生机械变形振动,晶振的机械变形振动反过来又会产生交变电场;当外加交变电压的频率与晶片的固有频率(取决于晶片尺寸)相等时,晶振与电路共同产生稳定的机械谐振和电气谐振,且频率稳定度很高。
图3-4 皮尔斯振荡电路
振荡电路的设计方法有多种,在单片机系统中,常用的是皮尔斯振荡电路,如图3-4所示。
一般来说,可将晶振分为两种类型:无源晶振和有源晶振。无源晶振一般称为晶体(Crystal),有源晶振一般称为振荡器(Oscillator)。在如图3-4所示的外部晶振电路中,常用的是晶体。
在电气上,晶振可以等效为一个电容和一个电阻并联后串联一个电容的二端网络,这个网络有两个谐振点,其中,频率较低的谐振是串联谐振,频率较高的谐振是并联谐振。晶振自身的特性使这两个谐振点的频率相当接近,在这个极窄的频率范围内,晶振呈感性(可以将其等效为一个电感),因此,只要在晶振的两端并联上合适的电容,就可以构成并联谐振电路。将这个并联谐振电路加入一个负反馈电路中,就可以构成正弦波振荡电路。由于将晶振等效为电感的频率范围很窄,因此,即使其他元件的参数有变化,这个振荡电路的频率也能保持相对稳定。晶振有一个重要的参数——负载电容值,选用与负载电容值相等的并联电容,就可以使振荡电路产生晶振标称的谐振频率。在振荡电路中,通常都是在一个反相放大器(注意:不是反相器)的两端接入晶振,并将两个电容分别接到晶振的两端,电容的另一端接地,这两个电容串联的容量应该等于负载电容值。晶振在上电启动后会振荡,产生脉冲波形,但该波形往往有谐波掺杂其中,这会影响单片机的工作稳定性,因此加上这两个电容可以将这些谐波滤除。如果考虑元件引脚的等效输入电容,则两个22pF的电容构成晶振的振荡电路就是较好的选择。晶振通过一定的外接电路生成频率和峰值稳定的正弦波,该正弦波在单片机内部调理电路的整形下成为方波,作为单片机内部时序电路工作的时钟信号。
在进行电路设计时,要尽量使整个振荡电路靠近MCU,同时尽量避免晶振电路旁有其他高频信号、大电流信号和较长布线存在,从而保证晶振工作时有较小的负载、正确的拓扑,以及相对稳定的电磁工作环境。注意:振荡电路的设计规则应该优先得到保证。
时钟是单片机运行的基础,时钟信号推动单片机内各部分执行相应的指令。时钟系统就是CPU的脉搏,像人的脉搏一样,人只有具备脉搏,才能做其他的事情,而单片机只有具备了时钟,才能执行指令,做其他的处理,时钟的重要性不言而喻。STM32内部集成的时钟模块功能更加丰富,包含时钟选择、倍频、输出、外设总线时钟配置等。STM32时钟系统如图3-5所示,图3-5也称为时钟树,理解了时钟树,STM32时钟的原理及应用都会了如指掌。每个时钟源在不使用时都可以单独打开或关闭,这样就可以优化系统功耗。
本部分选取一条时钟主线,并辅以代码(见3.2.5节),建议读者以先主后次的顺序来学习。
图3-5 STM32时钟系统
HSE由以下两种时钟源产生。
【HSE外部时钟】 如图3-6所示,在这种模式下,必须提供一个外部时钟源。外部时钟源的频率可高达25MHz。用户可以通过设置时钟信号控制寄存器RCC_CR中的HSEBYP位和HSEON位来选择该模式,此时,OSC_OUT引脚为高阻态。
【HSE外部晶振电路】 如图3-7所示,这个频率为4~16MHz的外部晶振的优点在于能产生非常精确的主时钟。
图3-6 HSE外部时钟
图3-7 HSE外部晶振电路
在图3-7中,谐振器和负载电容需要尽可能靠近振荡器的引脚,以减小输出失真和启动稳定时间。负载电容值必须根据选定的晶振进行调节。
HSI由内部8MHz的RC振荡器产生,可直接作为系统时钟或在2分频后作为PLL输入。HSI的RC振荡器能够在不需要任何外部器件的条件下提供系统时钟。它的启动时间比HSE外部晶振电路短。然而,即使在校准后,它的时钟频率精度仍较差。
许多电子设备要正常工作,通常需要外部的输入信号与内部的振荡信号同步,利用PLL就可以实现。PLL是一种反馈控制电路,其特点是利用外部输入的参考信号控制环路内部振荡信号的频率和相位。因为PLL可以实现输出信号频率对输入信号频率的自动跟踪,所以PLL通常用于闭环跟踪电路。PLL在工作过程中,当输出信号频率与输入信号频率相等时,输出电压与输入电压保持固定的相位差,即输出电压与输入电压的相位被锁住,这就是PLL名称的由来。
内部PLL可以用于倍频HSI的RC输出时钟或HSE外部晶振电路进入片内的输出时钟。PLL的设置(首先选择HSI振荡器除2或HSE振荡器为PLL的输入时钟,然后选择倍频因子)必须在其被激活前完成。一旦PLL被激活,PLL的参数就不能被改动。如果PLL中断在时钟中断寄存器中被允许,那么当PLL准备就绪时,可产生中断申请。如果需要在应用中使用USB接口,那么PLL必须被设置为输出48MHz或72MHz时钟,用于提供48MHz的USBCLK。
LSE接频率为32.768kHz的石英晶体,其可以由以下两个时钟源产生。
【LSE外部时钟】 如图3-8所示,在这种模式下,必须提供一个外部时钟源。
【LSE外部晶振电路】 如图3-9所示,是一个频率为32.768kHz的低速外部晶振或陶瓷谐振器。它的优点在于能为实时时钟部件(RTC)提供一个低速高精度的时钟源。RTC可以用于时钟/日历或其他需要计时的场合。
图3-8 LSE外部时钟
图3-9 LSE外部晶振电路
同样,在图3-9中,谐振器和负载电容需要尽可能靠近晶振引脚,这样能使输出失真和启动稳定时间减到最小。负载电容值必须根据选定的晶振进行调节。
LSI是一个低功耗时钟源,它可以在停止模式或待机模式下保持运行状态,为独立看门狗和自动唤醒单元提供时钟。LSI的频率大约为40kHz(30~60kHz)。LSI可以通过控制/状态寄存器(RCC_CSR)中的LSION位来启动或关闭,LSIRDY位指示低速内部振荡器是否稳定。在启动阶段,直到LSIRDY位被硬件设置为1,此时钟才被释放。如果在时钟中断寄存器(RCC_CIR)中允许中断,则将产生LSI中断申请。
综上,4种主要时钟的频率如下。
HSE,外部时钟,频率为4~16MHz,常用值为8MHz。
HSI,内部8MHz时钟,可直接作为系统时钟或在2分频后作为PLL输入。
LSE,外部32.768kHz时钟。
LSI,内部40kHz时钟。
时钟设置需要先考虑系统时钟的来源(是内部时钟、外部晶振,还是外部的振荡器,是否需要PLL),然后考虑内部总线和外部总线,最后考虑外设的时钟信号。应遵循先倍频作为处理器的时钟,再由内向外分频的原则。
如图3-5所示,STM32将时钟信号(通常为HSE)经过分频或倍频后,得到系统时钟;系统时钟经过分频,产生外设所需的时钟。其中,典型值为40kHz的LSI供独立看门狗使用;此外,它还可以为RTC提供时钟源。RTC的时钟源也可以选择LSE或HSE的128分频。RTC的时钟源通过备份域控制寄存器(RCC_BDCR)的RTCSEL[1:0]来选择。
STM32中有一个全速功能USB模块,其串行接口需要一个频率为48MHz的时钟源。该时钟源只能从PLL输出端获取,可以选择为1.5分频或1分频,即当需要使用USB模块时,PLL必须使能,并且时钟频率配置为48MHz或72MHz。其中,48MHz仅提供给USB串行接口SIE。
另外,STM32还可以选择一个时钟信号输出到MCO引脚(PA8),可以选择为PLL输出的2分频、HSI、HSE或系统时钟。
系统时钟SYSCLK是供STM32中绝大部分部件工作的时钟源。如图3-5所示,系统时钟可选择为PLL输出、HSI或HSE,HSI与HSE可以通过分频加至PLLSRC,并由PLLMUL进行倍频后,直接充当PLLCLK,经1.5分频或1分频后为USB接口提供一个48MHz的振荡频率。系统时钟频率的最大值为72MHz,通过AHB分频器分频后送给各个模块,AHB分频器输出的时钟送给如下八大模块使用。
送给AHB、内核、内存和DMA使用的HCLK。
通过8分频后送给CM3系统定时器。
直接送给CM3的自由运行时钟FCLK。
送给APB1分频器。APB1分频器可选择1/2/4/8/16分频,其输出一路供APB1外设使用(PCLK1,频率的最大值为36MHz),另一路送给定时器TIM2~TIM7的倍频器使用。这些倍频器可选择1倍频或2倍频,时钟输出供TIM2~TIM7使用。
送给APB2分频器。APB2分频器可选择1/2/4/8/16分频,其输出一路供APB2外设使用(PCLK2,频率的最大值为72MHz),另一路送给定时器TIM1和TIM8的倍频器使用。这两个倍频器可选择1倍频或2倍频,时钟输出供TIM1和TIM8使用。另外,APB2分频器还有一路输出供ADC分频器使用,分频后送给ADC模块使用。ADC分频器可选择2/4/6/8分频。
送给SDIO使用的SDIOCLK。
送给FSMC使用的FSMCCLK。
2分频后送给SDIO的AHB接口使用(HCLK/2)。
在以上的时钟输出中,有很多是带使能控制的,如AHB时钟、内核时钟,以及各种APB1外设、APB2外设等。当需要使用某外设时,一定要先使能对应的时钟。同样,在不使用某模块时,应将其对应的时钟关闭,从而降低系统功耗,达到节能的效果。当STM32系统时钟频率为72MHz时,在运行模式下,打开全部外设时的功耗电流为36mA,关闭全部外设时的功耗电流为27mA。
需要注意定时器TIM2~TIM4的倍频器,当APB1的分频为1时,其倍频值为1,定时器的时钟频率等于APB1的频率;当APB1的预分频系数为其他数值(预分频系数为2、4、8或16)时,它的倍频值为2。连接在APB1(低速外设)上的设备有电源接口、备份接口、CAN、USB、I2C1、I2C2、UART2、UART3、SPI2、窗口看门狗、TIM2、TIM3、TIM4。连接在APB2(高速外设)上的设备有UART1、SPI1、TIM1、ADC1、ADC2、所有普通I/O接口(PA~PE)、第二功能I/O接口。
STM32中有多种时钟信号,正确配置时钟是系统开发的第一步。STM32的时钟源一般有两种,即HSE和HSI。为了保证时钟的准确性,多采用8MHz晶体的HSE。8MHz的频率相对较低,通常要将外部时钟整数倍频后作为标准时钟使用。STM32系统一般先将HSE 9倍频后生成72MHz的PLL时钟,再将PLL时钟配置成系统时钟;设置系统时钟后,配置PCLK1和PCLK2时钟,分别用于APB1和APB2桥总线;桥总线直接决定了各个外设和功能模块的时钟频率。最终根据实际系统的需求,将所需外设时钟使能,只有这样,外设才能正常工作。
SystemClock_Config()函数代码如下:
SystemClock_Config()函数的作用是将系统时钟频率配置为64MHz。该函数的定义在main.c文件中main()函数的下面:
SystemClock_Config()函数将系统时钟源(System Clock Source)选为PLL(HSI),将系统时钟SYSCLK的频率配置为64MHz,将HCLK的频率配置为64MHz,将AHB的分频系数设定为1,将APB1的分频系数设定为2,将APB2的分频系数设定为1等。
练一练
读者可以在图3-5中按照HSI→PLLMUL→SYSCLK→AHB预分频器→APB1/APB2预分频器的流程用笔画一下。
RCC寄存器用于管理外部、内部和外设的时钟,它与时钟配置密切相关。RCC寄存器地址映射和复位值如表3-2所示。
表3-2 RCC寄存器地址映射和复位值
在库文件stm32f103xb.h中定义RCC寄存器组的结构体RCC_TypeDef:
从上面的宏定义中可以看出,编译器的预处理程序将程序中的RCC替换成((RCC_Ty-peDef*)0x40021000)。其中,0x40021000是RCC寄存器的存储映射首地址。首地址加上表3-2中各寄存器的偏移即寄存器在存储器中的位置。例如:
一旦STM32时钟模块出现问题,就会导致系统无法正常工作,特别是对时钟敏感的部分,如定时器、串口波特率、I2C时钟等。
主频是指CPU的时钟频率或系统时钟频率。主频变慢通常表现为程序运行变慢、卡顿、通信异常等。引起主频变慢的原因有时钟源选择错误、外部晶振频率与软件配置不正确、分频与倍频系数不正确、外部晶振电路不正常。
判断主频是否变慢最直接的方法是配置MCO,输出内部PLLCLK(或HSE),用示波器或逻辑分析仪测量其频率。
可能很多人遇到过定时器定时或快(2倍)或慢(0.5倍)的问题。由图3-10可知,STM32的APB时钟存在“×2”的判断。也就是说,如果APB的分频系数等于1,则“×1”;如果APB的分频系数不等于1,则“×2”。因此,在移植程序代码时,一定要注意时钟源(频率),否则会出现定时器定时或快或慢的问题。
图3-10 APB时钟或快或慢的成因
STM32通常使用外部晶振产生高速时钟信号。如果外部高速时钟失效,那么程序运行可能出现卡顿,这有可能是外界环境干扰造成的,也可能是晶振质量有问题。此时,应该使能时钟安全系统(Clock Security System,CSS)功能。使能CSS功能后,若HSE发生故障,则程序进入NMI中断,通过程序判断HSE是否失效;也可以将HSI切换为时钟源,重新配置时钟并启动程序,使程序恢复正常运行状态。
〖说明〗 STM32CubeMX默认配置是关闭CSS功能的。