自学STM32 - 理解时钟系统

作者:junziyang

数字系统中,指令的执行以时钟周期为基本时间单位。常用时钟周期的倒数来表征处理信息的快慢,称为时钟频率。比如主频为72MHz的MCU,其最短时钟周期是1/72微秒。STM32集成了大多数主流的外设(Peripheral),如USART、DMA、ADC等。不同的外设所需的时钟频率是不同的。为了指挥(同步)不同外设的工作,STM32内建了一套时钟系统。通过配置专门的寄存器,可以对时钟源和时钟频率进行设置,并通过总线架构,实现向不同外设(组)的时钟分配。除了配置时钟频率,时钟控制系统的另一个作用是降低功耗。由于外设众多,为了降低功耗,复位后外设驱动器的时钟一般都是关闭的,启用外设前需要通过时钟控制系统主动使能其时钟。

了解STM32的系统架构和时钟系统,可从宏观上理解STM32工作原理,掌握不同外设时钟的配置和初始化方法,加深对底层硬件和程序基本原理的理解。

注:如非特別声明,以下笔记内容均针对STM32F103ZET6而言。不同型号,细节可能存在差别。

一、STM32的系统架构

熟悉MCU的系统架构,对理解外设和时钟系统大有裨益。图1所示为MCU功能框图。可以看到芯片内部是十分复杂的,包含多个功能模块。我们先分区域来看一下整个芯片的功能布局。


图1.STM32系统架构框图。

1.1电源和时钟源

右上角主要是电源和时钟源,负责给芯片供电和提供时钟信号。粉红色填充的4个模块是时钟源,它们产生的时钟信号通过RCC(ResetandClockControl,复位与时钟控制)模块加载到AHB(AdvancedHigh-performanceBus)总线上。

1.2驱动模块

左上角橙色填充的模块为整个MCU的驱动(Master)模块,包括:

Cortex-M3核心:中间为CPU,上方为调试接口,下方为非线性向量中断控制器NVIC(NonlinearVectorInteruptController)。

DMA(DirectMemoryAccess)控制器:DMA1为7通道,DMA2为5通道。

总线(Bus):负责数据和控制信号的传递。

DMA专门负责处理不同速度的外设对存储器的访问请求和数据搬运。典型的应用就是将数据从一个地址区间复制到另外一个地址区间。经DMA请求,CPU把总线控制权交给DMA控制器,传输过程由DMA控制器来实行和完成,无需CPU主动干预,因此可以降低CPU的负担,提高效率。DMA传输结束后,总线控制权再交回给CPU。一个完整的DMA传输过程包括DMA请求、DMA响应、DMA传输、DMA结束4个步骤。

总线是数据和指令的传输通道。芯片中有多条总线,各自负责不同的信息传递功能:

ICodebus:InstructionCodebus,指令码总线,连接内核的ICode总线与闪存指令接口(FLITF,FLashInTerFace),负责从闪存(预)取指令。

DCodebus:DataCodebus,连接内核的DCode总线与总线矩阵,然后连接到闪存数据接口,负责数据传输(常量加载、调试访问等)。

Systembus:系统总线,连接内核的系统总线(外设总线)与总线矩阵。

DMAbus:DMA总线,连接DMA与总线矩阵。

可以看出,除了ICode总线是专线外,其余总线均连接到总线矩阵(BusMatrix)。与BusMatrix相连的总线有4进4出,分别链接左侧的驱动模块和右侧的从动模块,负责信息的上传下达。由于是一对多的服务,该模块采用了一种称为轮询调度的算法(RoundRobinalgorithm),来均衡各方需求。

1.3从动模块

从动模块(Slave)又称被动模块,是不能发号施令而只能唯命是从的模块。BusMatrix右侧的总线从上到下来看,依次去往Flash、SRAM(StaticRandom-AccessMemory,静态随机存取存储器)、FSMC(FlexibleStaticMemoryController,可变静态存储控制器,用于内存扩展)和AHB系统总线。

AHB总线又通过两个AHB/APB桥,同步连接到两个APB(AdvancedPeripheralBus)高级外设总线。所有外设都挂载在这两个外设总线上,其中APB2是全速外设总线,最高速度与AHB相同;而APB1是限速总线,最高速度通常只有AHB的一半。以STM32F103ZET6为例,APB2的速度可达全速72MHz,而APB1最高限速为36MHz。

另外,SDIO(SecurityDigitalInput/Output,安全数字输入输出)和RCC(ResetClockControl)直接挂载在AHB总线上。DMA1和DMA2经BusMatrix实际上也是与AHB总线相连。RCC通过AHB总线,为整个系统提供复位和时钟控制服务。

注意:

系统复位后,所有外设的时钟都是关闭的,因此使用外设前必须先使能其对应的时钟。AHB总线下方的外设通过设置RCC_AHBENR寄存器使能时钟,APB1和APB2总线下的外设则分别通过设置RCC_APB1ENR和RCC_APB2ENR寄存器使能时钟。AHB总线上方的SRAM和FLITF的时钟不受系统复位的影响。

不同的芯片型号支持的外设种类和数量可能会有些不同。稳妥起见建议查阅《ReferenceManual》-Memoryorganization章节来确定外设对应的总线及关联的寄存器。

二、STM32的时钟系统

再高端的MCU离开了时钟的同步也无法正常工作。就像人一样,没有了心跳,再好的身体条件也变得毫无意义。时钟系统就是MCU的心脏,RCC就是控制芯片内外各部分协调工作的总指挥。由于支持的外设众多,为了适应不同外设对时钟频率的需求,MCU内部构建了一套复杂的时钟系统,可以通过配置相关寄存器,来调配时钟频率、使能和复位外设时钟。我们先通过STM32CubeIDE或STM32CubeMX中的时钟配置图,从宏观上来了解一下时钟系统的结构,然后再学习相关的寄存器和时钟设置操作。

2.1STM32的时钟源

在STM322CubeIDE或STM32CubeMX中,可以通过图形界面,以交互式的方式来配置时钟。图2所示即为STM32CubeMx中STM32F103ZET6的ClockConfiguration界面。我们藉此来来分析一下时钟系统整体架构。


图2.STM32F103ZET6的时钟配置框图

LSI和HSI为内部时钟源,二者均为RC振荡源。由于RC时钟的精度较差,因此这两个内部时钟一般用于对时间精度要求不高的场合或在外部时钟出现故障时作为备用应急时钟。

LSE和HSE为外部时钟源,一般为高精度石英或陶瓷振荡器。

若按照时钟速度,可分为:

LSI和LSE为低速时钟:LSIRC频率约40kHz,LSE的频率为32.678kHz(2^15)。低速时钟主要用于实时时钟RTC(Real-TimeClock)和独立看门狗IWDG(IndepentWachDog)。

HSI和HSE为高速时钟:HSIRC频率约8MHz,HSE的频率为4-16MHz范围可选。高速时钟是系统的主时钟源,这两个时钟源根据需要经过倍频和分频产生系统时钟SYSCLK(SYStemCLocK)。

2.2RCC寄存器

时钟源的选择和开关、多路选择器的选通、分频/倍频系数的设置、时钟的锁定和复位等等,均是通过配置相应的RCC寄存器来实现的。STM32F103ZET6共有10个RCC寄存器,图3所示为这些寄存器的地址映射和复位值表。可以看出,RCC寄存器均为32位寄存器。与GPIO寄存器只能按字访问不同,RCC寄存器大都可以按字、字节或位访问。

图3.RCC寄存器地址映射与复位值

说明:

绝大多数可配置功能或外设的复位值为0,使用前需要主动配置寄存器进行使能。

最上方的RCC_CR寄存器有3个位的复位值是1。说明HSI是系统复位后的默认时钟。HSITRIM是用来校准HSI的修饰位。

中部的RCC_AHBENR寄存器有2个位的复位值为1。说明复位后FLITF和SRAM的时钟是默认开启的。

最下方RCC_CSR寄存器有2个位的复位值为1。PORRSETF和PINRSTF是上电复位和外部引脚复位的标志。

黄色背景标示的是一些标志位(Flag),一般由硬件来设置。

下面分别介绍各个RCC寄存器的功能。RCC寄存器配置的实际上是图2所示的时钟系统中相关部分的选通和设值。若计算机上安装了STM32CubeIDE或STM32CubeMx,可以新建一个项目,切换到ClockConfiguration界面,对照着学习。

1.RCC-CR

图4.系统时钟源构成

RCC-CR寄存器配位表如图5所示。

图5.RCC-CR寄存器配位表

低16位用来配置HSI时钟:

HSION,1使能,0关闭;

HSIRDY,标志位,时钟是否就绪(ReaDY);

HSITRIM,对电压和温度影响进行修饰(trimming),提高时钟精度;

HSICAL,用于时钟校准(calibration)。

高16位用来配置HSE和PLL:

HSEON,开/关时钟;

HSERDY,标志位,时钟是否就绪;

HSEBYP,时钟旁路(bypass),外接自定义时钟(方波、正弦、三角波等)须旁路HSE;

CSSON,开/关时钟安全系统(Clocksecuritysystem);

PLLON,开/关PLL;PLLRDY,标志位,PLL是否就绪。

说明:

HSI是RC时钟,环境参数变化(如电压和温度)会对时钟精度造成影响。RCC-CR寄存器设置了校准和温度/电压修饰位,可根据需要设置这些位,以提高时钟精度。ST出厂校正精度为1%@25℃,复位后HSICAL和HSITRIM恢复出厂设置。

CSS用来确保HSE时钟的安全运行。开启CSS后,如果HSE出现故障,CSS会触发一个NMI(Non-MaskableInterrupt)中断,自动将时钟切换到HSI。如果原时钟源是HSE+PLL,PLL也会被关闭。

从图3可以看出,复位后HSION的值为1,可见HSI是复位后默认的系统时钟,使用其他时钟源必须主动开启。

2.RCC-CFGR

RCC-CFGR为时钟配置寄存器(ClockConfigureRegister),用以配置图2中所示的多路选择器的选通、分频器/倍频器系数的寄存器。RCC-CFGR寄存器配位表如图6所示。CubeMX中的对应配置区域参考图7。

图6.RCC-CFGR寄存器配位表

图7.STM32CubeMX中AHB和APB总线的时钟配置

SW(SystmeclocksWitch),配置系统时钟选通器(图4中SystemClockMux)。配位逻辑:00-HSI;01-HSE;10-PLL;11-禁用。STM32CubeMX中,选通器通过选中图标上的单选框进行配置(如图中4所示)。

SWS(SystemclocksWitchStatus),系统时钟状态标志位。配位逻辑与SW相同。

HPRE(AHBprescaler),设置AHB主线预分频系数。系统时钟SYSCLK经AHBPrescaler分频,产生AHB总线时钟HCLK(参考图4和图7)。配位逻辑:0xxx-1(不分频);1000-2;1001-4;1010-8;1011-16:1100-64;1101-128;1110-256;1111-512。CubeMX中,分频/倍频系数通过下拉列表进行选择(如图4中所示)。

PPRE1和PPRE2(APBprescaler),分别设置APB1和APB2的预分频系数。HCLK分别经APB1Prescaler和APB2Prescaler分频,产生外设总线时钟PCLK1和PCLK2(参考图7)。配位逻辑:0xx-1(不分频);100-2;101-4;110-8;111-16。

ADCPRE(ADCprescaler),设置ADC预分频系数。ADC的时钟由PCLK2经ADCPrescaler进一步分频得到(参考图7)。配位逻辑:00-2;01-4;10-6;11-8。

PLLSRC(PLLsource),配置PLL时钟选通器(图4中PLLSourceMux)。配位逻辑:0-HSI2分频;1-HSE。

PLLXTPRE(PLLeXTernalclockprescaler):设置PLL外部时钟源(即HSE)预分频系数(参考图4,HSE与PLLSourceMux间的分频器)。配位逻辑:0-HSE不分频;1-HSE2分频。

PLLMUL(PLLmultiplicationfactor):设置PLL倍频系数(参考图4,*PLLMul)。根据时钟源频率设置合适的倍频系数,但最高输出频率不能高于芯片主频。配位逻辑:从0000递增到1110分别对应2-16倍,1111也对应16倍。

USBPRE(USBprescaler):设置USB预分频系数。PLLCLK经USBPrescaler分频产生48MHz的USB时钟(参考图4,右下角)。配位逻辑:0-1.5分频,PLLCLK为72MHz时对应48MHz;1-不分频。

MCO:配置主时钟输出选通器(参考图2左下角)。配位逻辑:0xx-关闭MCO;100-输出SYSCLK;101-输出HSI;110-输出HSE;111-输出PLL的2分频。

3.RCC_CIR

RCC_CIR为时钟中断寄存器(ClockInteruptRegister),用于管理时钟相关的中断。CC-CIR寄存器配位表如图8所示。

图8.RCC-CIR寄存器配位表

按功能可以分为3组:

以E结尾的(8-12位)为时钟就绪(事件)中断使能位(Enable),可读可写。设为1则对应的时钟稳定下来后会触发RDY中断;设为0则关闭中断。

以F结尾的(1-4,7位)为时钟就绪标志位(Flag),只可读。如果某时钟设置并触发了RDY中断,则由硬件将对应的位设为1。如果开启了CSS,HSE发生故障时会触发中断,设置CSSF位。

以C结尾的(16-20,23位)为时钟就绪中断清除位(Clear),只可写。与事件标志位是一一对应的,将某位设为1,可以将对应的标志位清除;设为0,则无影响。中断处理完成后,一般要主动清除标志位。

可以看出,RCC相关的事件有6个,其中5个事件可按需开启中断,而CSS中断只要开启CSS就会自动开启。

4.RCC_APB2ENR和RCC_APB2RSTR

从图3可以看出,与APB2总线上的外设相关的RCC寄存器有两个,分别为RCC_APB2ENR和RCC_APB2RSTR,前者称为APB2外设时钟使能寄存器(APB2peripheralenableregister),后者称为APB2外设复位寄存器(APB2peripheralresetregister)。两个寄存器的功能位是一一对应的。RCC_APB2ENR和RCC_APB2RSTR的配位表分别如图9和图10所示。

图9.RCC-APB2EN寄存器配位表

图10.RCC-APB2RSTR寄存器配位表

每个位对应一个外设端口,对应的外设从表格中的名称可以一目了然,毋庸赘言(IOP意为I/Oport,即GPIO)。向RCC_APB2ENR的某位写入1,可以使能对应的外设时钟,写入0则关闭对应外设的时钟;向RCC_APB2RST的某位写入1,则可以将对应的外设复位,写入0无影响。

注意:

从图2中可以看出,两个寄存器的复位值均为0,说明系统复位后所有APB2上的外设时钟都是关闭的,因此使用外设前必须主动使能对应的时钟。

这两个寄存器与前面学习过的GPIO的BRR和BSRR寄存器有本质的区别,BRR和BSRR是分别将ODR的对应位置0和置1。而这里的APB2ENR是使能外设的时钟,而APB2RSTR是将外设复位,即将外设的所有寄存器的值设为复位值表中的值。例如,将RCC_APB2RST中的IOPARST位置1,则GPIOA所有的寄存器被复位为默认值。

5.RCC_APB1ENR和RCC_APB1RSTR

与APB1总线上的外设相关的RCC寄存器也有两个,分别为RCCAPB1ENR和RCC_APB1RSTR,配位表分别如图11和图12所示,所有位的复位值也为0。除了管理的外设不一样,功能与APB2总线相关的两个寄存器完全一致,不再赘述。

图11.RCC-APB1ENR寄存器配位表

图12.RCC-APB1RSTR寄存器配位表

6.RCC_AHBENR

RCC_AHBENR为AHB外设时钟使能寄存器(AHBperipheralclockenableregister),用于管理与AHB总线相连的外设时钟。图13所示为寄存器配位图。

图13.RCC-AHBENR寄存器配位表

AHB总线的外设只有一个ENR寄存器,没有*RSTR。RCC_AHBENR原理同APB1和APB2的ENR寄存器,向某位写入1,使能对应外设时钟;写入0,关闭对应外设时钟。系统复位后,除FLITFEN和SARAMEN位的复位值为1,其余位复位值为0,说明复位后FLITF和SARAM的时钟是默认开启的。

7.RCC_BDCR

RCC_BDCR为备份区控制寄存器(Backupdomaincontrolregister),用于管理备份区的复位与时钟选择,以及开关RTC。所谓备份区是一组特殊的寄存器(BKP,backupregisters),用于在VDD断电后,依靠板载电池VBAT保存用户数据。备份区主要功能包括:侵入检测和RTC时钟校准。在图1中,备份区位于右上方,LSI时钟(XTAL32kHz)图标的下方,有一个TAMPER引脚引出,用于侵入监测或输出RTC闹钟脉冲等(详情查阅《Referencemanual》-BKP寄存器相关章节)。

图14.RCC-BDCR寄存器配位表

RCC_BDCR寄存器的配位图如图14所示。这个寄存器只用到了7位:

前三位:LSEON-使能LSE时钟;LSERDY-LSE就绪标志;LSEBYP-旁路LSE时钟。

RTCSEL:选择RTC的时钟源(图2右上角的RTCClockMux)。配位逻辑:00-无时钟;01-LSE;10-LSI;11-HSE的128分频。

RTCEN:RTC使能位,写入1开启RTC,写入0关闭RTC。

BDRST:写入1,整个备份区将被复位。

8.RCC_CSR

RCC_CSR为控制/状态寄存器(Control/statusregister),用以管理LSI时钟和系统复位标志。STM32系列MCU支持6种系统复位方式,无论哪种方式触发复位,除RCC_CSR和备份区寄存器外的所有寄存器都将被复位。备份域寄存器需要设置RCC_BDCR中的BDRST=1进行复位,RCC_CSR寄存器只有在发生电源复位是才会被复位。因此,当发生系统复位时,可以用RCC_CSR寄存器记录复位方式。RCC_CSR寄存器的配位图如图15所示。

图15.RCC-CSR寄存器配位表

26-31位为复位方式标志位(ReSeTFlag):

LPWRRSTF-Low-powerresetflag,低功耗复位标志。系统进入低功耗模式,导致系统复位时,由硬件将该位置1。

WWDGRSTF-Windowwatchdogresetflag,窗口看门狗复位标志。窗口看门狗复位发生时,由硬件将该位置1。

IWDGRSTF-Indepentwatchdogresetflag,独立看门狗复位标志。独立看门狗复位发生时,由硬件将该位置1。

SFTRSTF-Softwareresetflag,软件复位标志。软件复位发生时,由硬件将该位置1。

PORRSTF-POR/PDRresetflag,上电/掉电复位标志位。上电/掉电复位发生时,由硬件将该位置1。

PINRSTF-PINresetflag,引脚复位标志位。芯片有个NRST引脚(exteralreset见图2右上角),该引脚为低电平时触发系统复位。开发板上一般有个RST按钮,按下后会该引脚接地,触发系统复位。

24位RMVF(Removeflag)为复位标志清除位,向该位写入1将会把26-31位中的复位标志全部清除。

0位LSION和1位LSIRDY分别为LSI使能和就绪标志位。如前已述,HSE和HSI的对应功能位在RCC_CR寄存器中设置,LSE的在RCC_BDCR寄存器中设置。

三、时钟复位与初始化

3.1寄存器操作

在头文件(以F103系列标准库为例,HAL库中对应的头文件为)中定义了大量的宏、枚举类和结构体,对寄存器地址进行了映射。与RCC相关的地址映射摘录如下:

defineAHBPERIPH_BASE(PERIPH_BASE+0x20000)defineRCC((RCC_TypeDef*)RCC_BASE)typedefstruct{__IOuint32_tCR;//指向RCC首地址,后续依次便宜0x04(32bit)__IOuint32_tCFGR;__IOuint32_tCIR;__IOuint32_tAPB2RSTR;__IOuint32_tAPB1RSTR;__IOuint32_tAHBENR;__IOuint32_tAPB2ENR;__IOuint32_tAPB1ENR;__IOuint32_tBDCR;__IOuint32_tCSR;}RCC_TypeDef;

通过别名引用寄存器地址,向对应的位写入0或1,即可实现对寄存器的设置。时钟配置可以参考图2,按顺序依次配置相关寄存器。例如,先将系统时钟源设HSE,频率72MHz,然后开启GPIOB,GPIOE的时钟:

/*复位RCC相关寄存器*///CR不要清零,HSICAL出厂数据不确定RCC-APB1RSTR=0x00000000;RCC-APB2RSTR=0x00000000;RCC-AHBENR=0x00000014;RCC-APB2ENR=0x00000000;RCC-APB1ENR=0x00000000;RCC-CFGR=0x00000000;RCC-CIR=0x00000000;//关闭所有中断/*配置时钟*/RCC-CR|=0x00010001;//使能HSION/HSEONwhile(!(RCC-CR17));//等待HSERDY//配置PLLRCC-CFGR|=0x001D0402;//HSE9倍频PCLK2=72MHzRCC-CR|=0x01000000;//使能PLLFLASH-ACR|=0x32;//FLASH2个延时周期while(!(RCC-CR25));//等待PLLRDYRCC-APB2ENR|=0x00000048;//开启GPIOB,GPIOE的时钟

头文件中还定义了与RCC寄存器的功能位相关的宏,利用这些宏上述操作可改写为:

RCC-CR|=RCC_CR_HSION|RCC_CR_HSEON;//使能HSION/HSEONwhile((RCC-CRRCC_CR_HSERDY)==0);RCC-CFGR=~(RCC_CFGR_PLLXTPRE|RCC_CFGR_SW|RCC_CFGR_PLLMULL|RCC_CFGR_PLLSRC);RCC-CFGR|=RCC_CFGR_PLLXTPRE_PREDIV1|RCC_CFGR_SW_PLL|RCC_CFGR_PLLMULL9|RCC_CFGR_PLLSRC_HSE;RCC-CR|=RCC_CR_PLLON;while((RCC-CRRCC_CR_PLLRDY)==0);RCC-APB2ENR|=RCC_APB2ENR_IOPBEN|RCC_APB2ENR_IOPEEN;

小结:

如果新设的所有位均为1,准备好一个合适的Setmask(32bit十六进制数),直接|=即可。

如果新设的位中有0,需要先准备好一个Resetmask,=定位清零,然后再准备一个Setmask,|=写入新值。

为了便于计算Resetmask和Setmask,可以用Excel结合VBA编程做一个自动计算表。每个sheet对应一组寄存器进行统一管理。

用中预定义的宏操代码可读性和复用性好,但代码确实要复杂一些。好在常用的IDE都有代码提示功能,不需要记忆大量的宏名称。

3.2STD库RCC函数

STD库中RCC相关的库函数在stm32f10x_中声明,在stm32f10x_中实现。头文件stm32f10x_中为RCC相关寄存器中的功能位定义了宏名称,包括时钟源、各种外设、分频/倍频系数、多路选择器选项、标志位等定义,这些宏主要是为了配合库函数使用的。为了在库函数中实现按位(bitbanding)操作,提高效率,在stm32f10x_中,对部分寄存器在别名区的地址也进行了映射,为常用功能位定义了设置/复位掩码(Set/Resetmask)。

库函数是对寄存器操作的封装。STD库中RCC相关的库函数有30多个,下面按函数所操作的寄存器分组并简述其功能,可参照图3查看寄存器所关联的寄存器功能位/组。

1.跨寄存器函数

voidRCC_DeInit(void)复位CR、CFGR、CIR寄存器,这三个寄存器管理的是时钟配置和中断配置。复位后CIR寄存器的值与复位值表稍有不同,以C结尾的寄存器值被赋值为1,可能是因为F结尾的位是通过硬件设置的,只能通过软件设置C结尾的位来来触发硬件复位F结尾的位。

voidRCC_GetClocksFreq(RCC_ClocksTypeDef*RCC_Clocks)查询SYSCLK/HCLK/PCLK1/PCLK2/ADCCLK时钟的频率。该函数会根据当前时钟配置,计算并返回所查询时钟的频率,单位Hz。

FlagStatusRCC_GetFlagStatus(uint8_tRCC_FLAG)查询状态标志位的值。该函数用于查询CR、BDCR以及CSR中的*RDY位和*RST位(参见图3)。

2.RCC_CR

voidRCC_HSICmd(FunctionalStateNewState)开/关HSI时钟(HSION位)。

voidRCC_AdjustHSICalibrationValue(uint8_tHSICalibrationValue)调整HSI校准参数(HSITRIM[4:0]位)。取值范围0x00-0x1F。

voidRCC_HSEConfig(uint32_tRCC_HSE)配置HSE时钟(HSEON和HSEBYP位)。从函数定义可以看出,如果使能HSEBYP位,HSEON位必须同时使能,设置HSEBYP是为了使用别的外部时钟源,将HSE旁路,但HSE端口必须使能。

ErrorStatusRCC_WaitForHSEStartUp(void)等待HSE就绪。通过HSEON开启HSE时钟时,需要6个HSE时钟周期才会稳定下来,稳定下来后将HSERDY位置1。该函数中用一个dowhile循环调用RCC_GetFlagStatus(),查询RCC_FLAG_HSERDY,即HSERDY位的状态。直至HSERDY=SET或超时(1280次)。时钟就绪时返回SUCCESS,否则返回ERROR。

voidRCC_ClockSecuritySystemCmd(FunctionalStateNewState)开/关CSS(CSSON位)。位带操作。

voidRCC_PLLCmd(FunctionalStateNewState)开/关PLL(PLLON位)。位带操作。

3.RCC_CFGR

voidRCC_SYSCLKConfig(uint32_tRCC_SYSCLKSource)SYSCLK配置(SW[1:0]位)。

voidRCC_HCLKConfig(uint32_tRCC_SYSCLK)HCLK配置(HPRE[3:0]位)。

voidRCC_PCLK1Config(uint32_tRCC_HCLK)PCLK1配置(PPRE1[2:0]位)。

voidRCC_PCLK2Config(uint32_tRCC_HCLK)PCLK2配置(PPRE2[2:0]位)。

voidRCC_ADCCLKConfig(uint32_tRCC_PCLK2)ADCCLK配置(ADCPRE[1:0]位)。

voidRCC_PLLConfig(uint32_tRCC_PLLSource,uint32_tRCC_PLLMul)配置PLL时钟源(PLLSRC位和PLLXTPRE位)和倍频系数(PLLMUL位)。

voidRCC_MCOConfig(uint8_tRCC_MCO)配置系统时钟输出(MCO[2:0])。

uint8_tRCC_GetSYSCLKSource(void)查询系统时钟源(SWS[1:0])。

4.RCC_CIR

voidRCC_ITConfig(uint8_tRCC_IT,FunctionalStateNewState)中断配置(6个*E位)。

ITStatusRCC_GetITStatus(uint8_tRCC_IT)中断状态查询(6个*F位)。

voidRCC_ClearITPingBit(uint8_tRCC_IT)中断状态清除(6个*C位)。

5.RCC_BDCR

voidRCC_LSEConfig(uint8_tRCC_LSE)LSE时钟配置(LSEON位和LSEBYP位)。

voidRCC_RTCCLKConfig(uint32_tRCC_RTCCLKSource)RTC时钟源配置(RTCSEL[1:0]位)。

voidRCC_RTCCLKCmd(FunctionalStateNewState)开/关RTCRTC时钟(RTCEN位)。

voidRCC_BackupResetCmd(FunctionalStateNewState)复位备份区(BDRST位)。

6.RCC_CSR

voidRCC_LSICmd(FunctionalStateNewState)开/关LIS时钟(LSION位)。

voidRCC_ClearFlag(void)清除标志位(RMVF位)。项RMVF为写入1,清除复位*RSTF位。

7.开关外设时钟

voidRCC_AHBPeriphClockCmd(uint32_tRCC_AHBPeriph,FunctionalStateNewState)开/关AHB外设时钟。

voidRCC_APB2PeriphClockCmd(uint32_tRCC_APB2Periph,FunctionalStateNewState)开/关APB2外设时钟。

voidRCC_APB1PeriphClockCmd(uint32_tRCC_APB1Periph,FunctionalStateNewState)开/关AHB1外设时钟。

voidRCC_APB2PeriphResetCmd(uint32_tRCC_APB2Periph,FunctionalStateNewState)复位APB2外设时钟。

voidRCC_APB1PeriphResetCmd(uint32_tRCC_APB1Periph,FunctionalStateNewState)复位APB1外设时钟。

小结:

几乎每个寄存器功能位/组,都有与之对应的库函数。

*cmd函数为功能使能/关闭函数;*Config为功能配置函数;*Init为复位或初始化函数;Get*为查询函数;Wait*为等待函数;Clear*标志位为清除函数。

示例:

RCC_HSEConfig(RCC_HSE_ON);//使能HSERCC_PLLConfig(CC_PLLSource_HSE_Div1,RCC_PLLMul_9);//配置PLLRCC_PLLCmd(ENABLE);//使能PLLRCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//选通PLL作为系统时钟源RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE,ENABLE);//开启GPIOB,GPIOE的时钟

说明:

STD库中的时钟配置可以按上述方式,通过调用库函数配置。其实有更简单的方法,在system_中,STMicroelectronicst已经实现了各种可能的时钟配置,我们只需打开相应的宏定义即可。system_中的第一个宏定义模块中,去掉/*精品长文创作季文章首发挑战赛#

发布于 2025-03-09
14
目录

    推荐阅读