STM32微控制器可以选择内部时钟(内部RC振荡器),也可以选择外部时钟(外部晶振)。但如果使用内部RC振荡器而不使用外部晶振,必须清楚以下几点:(1)对于100脚或144脚的产品,OSC_IN应接地,OSC_OUT应悬空。(2)对于少于100脚的产品,有两种接法:方法1:OSCIN和OSCOUT分别通过1Ok欧电阻接地。此方法可提高EMC性能。方法2:分别重映射OSCIN和OSCOUT至PDO和PD1,再配置PDO和PD1为推挽输出并输出0。此方法相对于方法1,可以减小功耗并节省两个外部电阻。(3)内部8MHz的RC振荡器的误差在1%左右,内部RC振荡器的精度通常比用HSE(外部晶振)要低十倍以上。STM32的ISP就是利用了HSI(内部RC振荡器)。系统时钟的选择是在启动时进行的,复位时内部8MHz的RC振荡器被选为默认的CPU时钟,随后可以选择外部的、具有失效监控功能的4-16MHz时钟,当检测到外部时钟失效后,它将被隔离,系统将自动地切换到内部的RC振荡器。2.STM32时钟源在STM32中,有5个时钟源,分别为HSI、HSE、LSI、LSE、PLL。(1)HSI是高速内部时钟,RC振荡器,频率为8MHz。(2)HSE是高速外部时钟,可接石英谐振器、陶瓷谐振器,或者接外部时钟源,它的频率范围为4MHz~16MHz。(3)LSI是低速内部时钟,RC振荡器,频率为4OkHz。它主要用于启动看门狗和通过程序选择启动RTC(RTC用于从停机/待机模式下自动唤醒系统)。(4)LSE是低速外部时钟,接频率为32.768kHz的石英晶体。也可以用来启动RTC。(5)PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择2~16倍,但是其输出频率最大不得超过72MHz。3.STM32时钟树的输入与输出STM32微控制器的时钟树是可配置的,其时钟输入源与最终达到外设处的时钟速率不再有固定的关系。要学会STM32,必须理解时钟树的输入和输出关系。现以图4-5中的圆框数字序号标示的部分所示,说明时钟输入与时钟输出之间的关系,输入至输出之间的路径一可表示为1-2-3-4-5-6-7,当然也可以选择路径二:1-5-6-7。此处以路径一为例,做以下具体兮析。117
117 STM32微控制器可以选择内部时钟(内部RC振荡器),也可以选择外部时钟(外部晶振)。 但如果使用内部RC振荡器而不使用外部晶振,必须清楚以下几点: (1)对于100脚或144脚的产品,OSC_IN应接地,OSC_OUT应悬空。 (2)对于少于100脚的产品,有两种接法: 方法1: OSC_IN和OSC_OUT分别通过10k欧电阻接地。此方法可提高EMC性能。 方法2:分别重映射OSC_IN和OSC_OUT至PD0和PD1,再配置PD0和PD1为推挽 输出并输出 0。此方法相对于方法1,可以减小功耗并节省两个外部电阻。 (3)内部8MHz的RC振荡器的误差在1%左右,内部RC振荡器的精度通常比用HSE (外部晶 振)要低十倍以上。STM32的ISP就是利用了HSI(内部RC振荡器)。 系统时钟的选择是在启动时进行的,复位时内部8MHz的RC振荡器被选为默认的CPU时 钟,随后可以选择外部的、具有失效监控功能的4-16MHz时钟,当检测到外部时钟失效后, 它将被隔离,系统将自动地切换到内部的RC振荡器。 2.STM32时钟源 在STM32中,有5个时钟源,分别为HSI、HSE、LSI、LSE、PLL。 (1)HSI是高速内部时钟,RC振荡器,频率为8MHz。 (2)HSE是高速外部时钟,可接石英谐振器、陶瓷谐振器,或者接外部时钟源,它的 频率范围为4MHz〜16MHz。 (3)LSI是低速内部时钟,RC振荡器,频率为40kHz。它主要用于启动看门狗和通过程 序选择启动RTC(RTC用于从停机/待机模式下自动唤醒系统)。 (4)LSE是低速外部时钟,接频率为32.768kHz的石英晶体。也可以用来启动RTC。 (5)PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选 择2〜16倍,但是其输出频率最大不得超过72MHz。 3.STM32时钟树的输入与输出 STM32微控制器的时钟树是可配置的,其时钟输入源与最终达到外设处的时钟速率不再 有固定的关系。要学会STM32,必须理解时钟树的输入和输出关系。现以图4-5中的圆框数字 序号标示的部分所示,说明时钟输入与时钟 输出之间的关系,输入至输出之间的路径一可 表示为1-2-3-4-5-6-7,当然也可以选择路径二:1-5-6-7。此处以路径一为例,做以下具体 兮析
USBCLKASRUSB48MHz★toUSBinterfacePrescaler/1,1.5HCLK72MHzmaOAHBbus,cmemoryandDOMAclocke(37stoCortexSystemtimecSw6SRCPLLMUL+FCLKCortex6free running clockAHBAPB1x16SYSCPCLK136MHzmaxPrescalerPrescalerX3.X472MH2PLLCLKtoAPB1PL/1,2.512/1,2,4,8,16perpheralsPeriphetal ClockHSE4Enable (13 bits)toTIM2.3TIM2.3.4TIMXCLKx1.2MultiplerPeripheral ClockEnable (3 bits)APB2PLLXTPRE72MHzmaxPCLK2PrescalerOAPBOSC_OUTT1.2.4.8.164-16MHzperipheralsPeripheralCiockHSEOSCEnable (11bits)OSC_IN2toTIM1TIMITimer1TIM1CLKx1.2MultiplierParialClock/12Enable (fbit)ADCtoADCOSC32INtoRTCLSEOSCPrescaleSADCCLK12.4.6.8RTCCLK32.768 kHzOS32OUTRTCSEL[1:0]toindepenentWatchdog (IWDGLSIRCIWDGCLKLegend:Main12PLLCLKHSE = High Speed Extemal ciock signalClockOusnutMCOHSIHS=HighSpeedintermalclocksignalHSELS=LowSpeedintemalcioksignalLSE=LowSpeedExtemalclocksignalSYSCLKMCO图4-5STM32微控制器的时钟树1-输入,外部晶振(HSE),可选为4~16MHz。2-第-个分频器PLLXTPRE,可以选择1分频或2分频。3-时钟源选择,开关PLLSRC(PLLentryclocksource),我们可以选择其输出,输出为外部高速时钟(HSE)或是内部高速时钟(HSI)。这里选择输出为HSE。4-PLL(锁相环),具有倍频功能(输入倍频因矛PLLMUL,2~16倍),经过PLL的时钟称为PLLCLK。倍频因子设定为9倍频,也就是说,经过PLL之后,时钟从原来8MHz的HSE变为72MHz的PLLCLK。5-开关SW,经过这个开关之后就是STM32的系统时钟(SYSCLK)了。通过这个开关,可以切换SYSCLK的时钟源,可以选择为HSI、PLLCLK、HSE。我们选择为PLLCLK时钟,所以SYSCLK就为72MHz了。6-AHB预分频器(分频系数为1~512)。如果选为1,分频系数为1。7-APB2预分频器(分频系数为1,2,4,8,16)。如果选为1,则分频系数为1,所以高速外设APB2(PCLK2)为72MHz。4.STM32中几个与时钟相关的概念SYSCLK:系统时钟,STM32大部分器件的时钟来源。它由AHB预分频器分配到各个部118
118 图4-5 STM32微控制器的时钟树 1-输入,外部晶振(HSE),可选为4〜16MHz。 2-第-个分频器PLLXTPRE,可以选择1分频或2分频。 3-时钟源选择,开关PLLSRC(PLL entry clock source),我们可以选择其输出,输 出 为外部高速时钟(HSE)或是内部高速时钟(HSI)。这里选择输出为HSE。 4-PLL (锁相环),具有倍频功能(输入倍频因矛PLLMUL,2〜16倍),经过PLL的时钟称 为PLLCLK。倍频因子设定为9倍频,也就是说,经过PLL之后,时钟从原来8MHz的 HSE 变为 72MHz的PLLCLK。 5-开关SW,经过这个开关之后就是STM32的系统时钟(SYSCLK)了。通过这个开关,可以 切换SYSCLK的时钟源,可以选择为HSI、PLLCLK、HSE。我们选择为PLLCLK时钟,所以 SYSCLK就为72MHz了。 6-AHB预分频器(分频系数为1〜512)。如果选为1,分频系数为1。 7-APB2预分频器(分频系数为1,2,4,8,16)。如果选为1,则分频系数为1,所以高 速外设APB2(PCLK2)为72MHz。 4.STM32中几个与时钟相关的概念 SYSCLK:系统时钟,STM32大部分器件的时钟来源。它由AHB预分频器分配到各个部
件。HCLK:由AHB预分频器直接输出得到,它是高速总线AHB的时钟信号,提供给存储器、DMA及Cortex内核,是Cortex内核运行的时钟,CPU主频就是这个信号,它的大小与STM32运算速度、数据存取速度密切相关。FCLK:同样由AHB预分频器输出得到,是内核的“自由运行时钟”(freerunningclock)。“自由”表现在它不来自时钟HCLK,因此在HCLK时钟停止时FCLK也会继续运行。它的存在,可以保证在处理器休眠时,也能够采样中断和跟踪休眠事件,它与HCLK互相同步。PCLK1:外设时钟,由APB1预分频器输出得到,最大频率为36MHz,提供给挂载在APB1总线上的外设(低速外设)。PCLK2:外设时钟,由APB2预分频器输出得到,最大频率可为72MHz,提供给挂载在APB2总线上的外设.(高速外设)。5.时钟输出的使能及其流程在以上的时钟输出中有很多是带使能控制的,如AHB总线时钟、内核时钟、各种APB1外设时钟、APB2外设时钟等。当需要使用某模块时,必须先使能对应的时钟。需要注意的是定时器的倍频器,当APB的分频为1时,它的倍频值为1,否则它的倍频值就为2。连接在APB1上的设备(低速外设)有:电源接口、备份接口、CAN、USB、I2C1、I2C2UART2、UART3、SPI2、窗口看门狗、Timer2、Timer3、Timer4。注意:USB模块虽然需要一个单独的48MHz时钟信号,但它不是供USB模块工作的时钟,而只是提供给串行接口引擎(SIE)使用的时钟。USB模块工作的时钟应该是由APB1提供的。连接在APB2上的设备(高速外设)有:GPIO_A-E、USART1、ADC1、ADC2、ADC3、TIM1、TIM8、SPII、AFIO。其中需要理解的是APB1和APB2的区别,APB1上面连接的是低速外设,包括电源接口、备份接口、CAN、USB、IC1、I'C2、UART2、UART3等等,APB2上面连接的是高速外设,包括UART1、SPI1、Timer1、ADC1、ADC2、所有普通IO口(PA~PE)、第二功能IO口等。APB2下面所挂的外设的时钟要比APB1的高。在以上的时钟输出中,有很多是带使能控制的,例如AHB总线时钟、内核时钟、各种APB1外设、APB2外设等等。当需要使用某模块时,记得一定要先使能对应的时钟。以下是时钟设置的基本流程。假设,使用HSE时钟,并且使用ST的固件库函数,那么在程序中设置时钟参数的流程如下。第1步:将RCC寄存器重新设置为默认值,即调用函数RCCDelnit;第2步:打开外部高速时钟晶振HSE,调用函数RCC_HSEConfig(RCC_HSE_ON);第3步:等待外部高速时钟晶振工作,调用HSEStartUpStatus=RCC_WaitForHSEStartUp() ;第4步:设置AHB时钟,即调用函数RCC_HCLKConfig;第5步:设置高速AHB时钟,即调用函数RCC_PCLK2Config;119
119 件。 HCLK:由AHB预分频器直接输出得到,它是高速总线AHB的时钟信号,提供给存储 器、 DMA及Cortex内核,是Cortex内核运行的时钟,CPU主频就是这个信号,它的大小与STM32运 算速度、数据存取速度密切相关。 FCLK:同样由AHB预分频器输出得到,是内核的“自由运行时钟”(free running clock)。“自由”表现在它不来自时钟HCLK,因此在HCLK时钟停止时FCLK也会继续运 行。 它的存在,可以保证在处理器休眠时,也能够采样中断和跟踪休眠事件,它与HCLK 互相同 步。 PCLK1:外设时钟,由APB1预分频器输出得到,最大频率为36MHz,提供给挂载在APB1总 线上的外设(低速外设)。 PCLK2:外设时钟,由APB2预分频器输出得到,最大频率可为72MHz,提供给挂载在 APB2总线上的外设.(高速外设)。 5.时钟输出的使能及其流程 在以上的时钟输出中有很多是带使能控制的,如AHB总线时钟、内核时钟、各种 APB1 外设时钟、APB2外设时钟等。 当需要使用某模块时,必须先使能对应的时钟。需要注意的是定时器的倍频器,当 APB的分频为1时,它的倍频值为1,否则它的倍频值就为2。 连接在APB1上的设备(低速外设)有:电源接口、备份接口、CAN、USB、I2C1、 I2C2、 UART2、UART3、SPI2、窗口看门狗、Timer2、Timer3、Timer4。注意:USB模块虽然需要一 个单独的48MHz时钟信号,但它不是供USB模块工作的时钟,而只是提供给串行接口引擎 (SIE)使用的时钟。USB模块工作的时钟应该是由APB1提供的。 连接在APB2上的设备(高速外设)有:GPIO_A-E、USART1、ADC1、ADC2、ADC3、TIM1、 TIM8、SPI1、AFIO。 其中需要理解的是APB1和APB2的区别,APB1上面连接的是低速外设,包括电源接口、备 份接口、CAN、USB、I 2 C1、I 2 C2、UART2、UART3 等等,APB2上面连接的是高速外设,包括UART1、 SPI1、Timer1、ADC1、ADC2、所有普通IO口(PA~PE)、第二功能IO口等。APB2下面所挂的外 设的时钟要比APB1的高。 在以上的时钟输出中,有很多是带使能控制的,例如AHB总线时钟、内核时钟、各种APB1 外设、APB2外设等等。当需要使用某模块时,记得一定要先使能对应的时钟。 以下是时钟设置的基本流程。 假设,使用HSE时钟,并且使用ST的固件库函数,那么在程序中设置时钟参数的流程如 下。 第1步:将RCC寄存器重新设置为默认值,即调用函数RCC_Delnit; 第2步:打开外部高速时钟晶振HSE,调用函数RCC_HSEConfig(RCC_HSE_ON); 第3步:等待外部高速时钟晶振工作,调用HSEStartUpStatus=RCC_WaitForHSEStartUp (); 第4步:设置AHB时钟,即调用函数RCC_HCLKConfig; 第5步:设置高速AHB时钟,即调用函数RCC_PCLK2Config;
第6步:设置低速AHB时钟,即调用函数RCC_PCLK1Config;第7步:设置PLL,即调用函数RCC_PLLConfig;第8步:打开PLL,即调用函数RCCPLLCmd(ENABLE);第9步:等待PLL工作,while(RCC_GetFlagStatus(RCC_FLAG—PLLRDY)==RESET);第10步:设置系统时钟,即调用函数RCC_SYSCLKConfig;第11步:判断PLL是否是系统时钟,while(RCC_GetSYSCLKSource(!=OxO8);第12步:打开要使用的外设时钟,即调用函数RCCAPB2PeriphClockCmd(;或者RCC_APB1PeriphClockGmdO。4.3STM32程序开发的模式STM32单片机系统的开发模式通常有两种:一是基于寄存器开发二是基于ST公司官方提供的固件库开发。当然,还有一种是基于嵌入式操作系统的开发模式,4.3.1基于寄存器的开发模式1.理论基础(1)了解各功能部件的功能,主要有总线、总线桥、GPIO、定时器和计数器、串行通信USART、串行接口总线(SPI、I2C)、中断及其机理等。(2)熟悉主要寄存器【控制寄存器(模式寄存器)、状态寄存器、数据寄存器、中断寄存器等】,掌握主要寄存器的功能、每个寄存器位的定义与作用,通过赋值语句来设置或获取相关寄存器的值。(3)明确程序开发要使用的功能部件及其程序设计要点,能按照要求初始化相关寄存器、查询和设置相关寄存器。2.工程模板的建立基于寄存器的程序开发模式可以使用更加精简的工程模板。但是,也可以与基于库函数的开发模式一起,使用统一的工程模板。关于如何建立STM32单片机系统的工程模板的内容比较复杂,这里先不不予展开。3.实践基础(1)根据欲开发的程序的功能与性能要求,合理规划程序模块,合理选择STM32的功能部件,根据各功能部件程序设计的要点,设计好各模块程序的流程图,(2)来用分而治之的思想,先设计、调试各个模块的程序。(3)最后将各模块程序有机组合,再对程序进行统调和测试。4.基于寄存器的开发模式的特点(1)特点一:与硬件关系密切。程序编写直接面对底层的部件、寄存器和引脚。(2)特点二:要求对STM32的结构与原理把握得很清楚。要求编程者比较熟练地掌握STM32单片机的体系架构、工作原理,尤其是对寄存器及其功能要很熟悉。(3)特点三:程序代码比较紧、短小,代码完余相对较少,因此源程序生成的机器120
120 第6步:设置低速AHB时钟,即调用函数RCC_PCLKlConfig; 第7步:设置PLL,即调用函数RCC_PLLConfig; 第8步:打开 PLL,即调用函数RCC_PLLCmd(ENABLE); 第9步:等待 PLL工作,while(RCC_GetFlagStatus(RCC_FLAG—PLLRDY)== RESET); 第10步:设置系统时钟,即调用函数RCC_SYSCLKConfig; 第11步:判断PLL是否是系统时钟,while(RCC_GetSYSCLKSource()!=0x08); 第12步:打开要使用的外设时钟,即调用函数RCC_APB2PeriphClockCmd();或者 RCC_APB1PeriphClockGmd()。 4.3 STM32程序开发的模式 STM32单片机系统的开发模式通常有两种:一是基于寄存器开发;二是基于ST公司官方 提供的固件库开发。当然,还有一种是基于嵌入式操作系统的开发模式。 4.3.1 基于寄存器的开发模式 1.理论基础 (1)了解各功能部件的功能,主要有总线、总线桥、GPIO、定时器和计数器、串行通 信USART、串行接口总线(SPI、I2C)、中断及其机理等。 (2)熟悉主要寄存器【控制寄存器(模式寄存器)、状态寄存器、数据寄存器、中断 寄 存器等】,掌握主要寄存器的功能、每个寄存器位的定义与作用,通过赋值语句来设置或 获取相关寄存器的值。 (3)明确程序开发要使用的功能部件及其程序设计要点,能按照要求初始化相关寄存 器、查询和设置相关寄存器。 2.工程模板的建立 基于寄存器的程序开发模式可以使用更加精简的工程模板。但是,也可以与基于库函 数的开发模式一起,使用统一的工程模板。关于如何建立STM32单片机系统的工程模板的内 容比较复杂,这里先不不予展开。 3.实践基础 (1)根据欲开发的程序的功能与性能要求,合理规划程序模块,合理选择STM32的功 能部件,根据各功能部件程序设计的要点,设计好各模块程序的流程图。 (2)釆用分而治之的思想,先设计、调试各个模块的程序。 (3)最后将各模块程序有机组合,再对程序进行统调和测试。 4.基于寄存器的开发模式的特点 (1)特点一:与硬件关系密切。程序编写直接面对底层的部件、寄存器和引脚。 (2)特点二:要求对STM32的结构与原理把握得很清楚。要求编程者比较熟练地掌握 STM32单片机的体系架构、工作原理,尤其是对寄存器及其功能要很熟悉。 (3)特点三:程序代码比较紧凑、短小,代码冗余相对较少,因此源程序生成的机器
码比较短小。(4)特点四:开发难度较大、开发周期较长,后期维护、调试比较烦琐。在编程过程中,必须十分熟悉所涉及的寄存器及其工作流程,必须按照要求完成相关设置、初始化工作,开发难度相对较大。如果要扩充硬件、增加功能,这些后期的维护升级,相较于基于固件库的开发模式,要困难很多。4.3.2基于固件库的开发模式1.理论基础(1)了解各功能部件的功能,主要有总线、总线桥、GPIO、定时器和计数器、串行通信USART、串行接口总线(SPI、I2C)、中断及其机理等。(2)熟悉固件库中相关部件所涉及的主要库函数各自的功能、调用要领、注意事项包括系统初始化等函数。2.工程模板工程模板的建立比较复杂,单对基于于固件库函数的工程模板现在有了图形化工程模板建立软件STM32CubeMX,下面有关章节最详细说明。3.实践基础(1)根据欲开发的程序的功能与性能要求,合理规化程序模块,合理选择STM32的功能部件,根据各功能部件程序设计的要点,设计好各模块程序的流程图。(2)采用分而治之的思想,先设计、调试各个模块南程序。3)最后将各模块有机组合,对程序进行统调和测试。4.基于固件库函数的开发模式的特点(1)特点一:与硬件关系比较疏远。由于函数的封装,使得与底层硬件接口的部分被封装,编程时不需要太关注硬件。(2)特点二:对STM32的结构与原理把握的要求相对较低。只要对硬件原理有一定的理解,能按照库函数的要求给定函数参数、利用返回值,即可调用相关函数,实现对某个部件、寄存器的操作。(3)特点三:程序代码比较烦琐、偏多。由于考虑到函数的稳健性、扩充性等因素,使得程序的亢余部分会较大。(4)特点四:开发难度较小、开发周期较短,后期维护、调试比较容易。外围设备的参考函数比较容易获取,也比较容易修改。4.3.3基于操作系统的开发模式1.操作系统的基本概念操作系统(OperatingSystem),简称oS,而嵌入式操作系统(EmbeddedOperatingSystem),简称EOS,它专门用于嵌入式系统。操作系统有实时和非实时之分,实时系统主要用于对时间响应要求比较高的场合。常用的嵌入式操作系统有:small_RTOS,卜C/OS-II,clinux,Linux,WinCE,eCOS,121
121 码比较短小。 (4)特点四:开发难度较大、开发周期较长,后期维护、调试比较烦琐。在编程过程 中,必须十分熟悉所涉及的寄存器及其工作流程,必须按照要求完成相关设置、初始化工 作,开发难度相对较大。如果要扩充硬件、增加功能,这些后期的维护升级,相较于基于 固件库的开发模式,要困难很多。 4.3.2 基于固件库的开发模式 1.理论基础 (1)了解各功能部件的功能,主要有总线、总线桥、GPIO、定时器和计数器、串行通 信USART、串行接口总线(SPI、I2C)、中断及其机理等。 (2)熟悉固件库中相关部件所涉及的主要库函数各自的功能、调用要领、注意事项, 包括系统初始化等函数。 2.工程模板 工程模板的建立比较复杂,单对基于于固件库函数的工程模板现在有了图形化工程模 板建立软件STM32CubeMX,下面有关章节最详细说明。 3.实践基础 (1)根据欲开发的程序的功能与性能要求,合理规化程序模块,合理选择STM32的功能 部件,根据各功能部件程序设计的要点,设计好各模块程序的流程图。 (2)采用分而治之的思想,先设计、调试各个模块南程序。 (3)最后将各模块有机组合,对程序进行统调和测试。 4.基于固件库函数的开发模式的特点 (1)特点一:与硬件关系比较疏远。由于函数的封装,使得与底层硬件接口的部分被 封装,编程时不需要太关注硬件。 (2)特点二:对STM32的结构与原理把握的要求相对较低。只要对硬件原理有一定的 理解,能按照库函数的要求给定函数参数、利用返回值,即可调用相关函数,实现对某个 部 件、寄存器的操作。 (3)特点三:程序代码比较烦琐、偏多。由于考虑到函数的稳健性、扩充性等因素, 使得程序的冗余部分会较大。 (4)特点四:开发难度较小、开发周期较短,后期维护、调试比较容易。外围设备的 参考函数比较容易获取,也比较容易修改。 4.3.3 基于操作系统的开发模式 1.操作系统的基本概念 操作系统(Operating System),简称0S,而嵌入式操作系统(Embedded Operating System), 简称EOS,它专门用于嵌入式系统。 操作系统有实时和非实时之分,实时系统主要用于对时间响应要求比较高的场合。 常用的嵌入式操作系统有:small_RT0S,卜C/OS-II, clinux, Linux, WinCE, eCOS