RCC时钟模块并不好理解,初次接触我也是一头雾水,而且我真正掌握它的时候也比较晚,是我在学习用寄存器控制开发板时才真正了解他的运行原理和规律,但我为什么重新修订后却放在了前列,因为这是整个嵌入式的基础之一,初学者是比较难,但是我还是希望最好能够掌握,因为实时性对于嵌入式系统很重要,而基础正是要了解从系统时钟到你选定的每一个模块它的时钟频率,理解这个模块对于学习以后所有模块都很有用,闲话不多说,进入正题:
初看此图是不是感觉太复杂了,事实上我第一次看这张图的时候也是的,完全理不清结构,但是下面我带你由浅到深来理解这幅图。
(1)时钟源(4个晶振源,1个中介源)
HSI(RC):内部高速晶振,~8MHz
HSE(Osc):外部高速晶振(与电路设计时选择有关,25MHz)
LSE(Osc):外部低速晶振(默认为32.768KHZ)
LSI(RC):内部低速晶振,~40KHz
PLLCLK:锁向环倍频输出,最大频率小于72MHz,注:PLLCLK来源HSE,HSE/2,HSI/2
(2)系统时钟源
SYSCLK:系统时钟
来源HSI,PLLCLK,HSE,若CSS(时钟监视系统)检测到HSE失效,SYSCLK = HSI;
(3)主要输出时钟源
HCLK:高性能总线时钟(SYSCLK通过AHB Prescaler,最高72MHZ)
PCLK1:外设1区域时钟(通过APB1 Prescaler,最高36MHZ)
PCLK2:外设2区域时钟(通过APB2 Prescaler,最高72MHZ)
ADCCLK:ADC外设时钟(PCLK2通过ADC Prescaler)
此外APB1,APB2外设时钟除了给对应外设区域提供时钟外,还可通过TIMERX Prescaler分配不 同的定时器时钟。
USBCLK:通用串行接口时钟(PLLCLK通过USB Prescaler,等于48MHZ)
RTCCLK:实时时钟,来源LSI,LSE,HSE/128
IWDGCLK:独立看门狗时钟,来源LSI
MCO: 输出内部时钟
从上面看,我们前面提到的GPIOD外设还有后面的USART,CAN等的时钟都没有提到,为什么,其实它们包含在PCLK1,PCLK2这两个外设区域时钟里,也就是说他们的时钟与该外设区域的时钟是相等的。下面是STM32Fxxx固件函数库中15.2.22以及15.2.23所提到的图,包含所有外设对应的区域:
PCLK1时钟区域:
PCLK2时钟区域:
通过上诉两张图可以清晰的知晓我在第一章节流水灯时时钟使能如此选择APB2外设的原因,当然我是以stm32f10x为例的,如果你使用不同的芯片就要去查相应的寄存器手册。了解了这些其实已经对系统时钟掌握差不多了,下面我就以寄存器控制方式展现嵌入式时钟的配置(库函数操作对于理解时钟配置过程的帮助并不大,特别只是单纯调用而没有理解每个函数内容的情况下)。
(4)系统时钟配置实例(以使用HSE晶振,最后系统时钟为50MHZ为例)
注:RCC寄存器功能可参考《STM32中文参考手册》6.3(互联型产品)
unsigned char PLL = 4; //PLL为设定放大的倍数 unsigned char temp = 0; //1.HSE时钟使能 //时钟控制寄存器 RCC->CR RCC->CR &= 1<<16; //使能HSE While(!(RCC-CR)>>17)); //判断HSE就绪标志位 //2.配置PLL,APB2,APB1,AHB //时钟配置寄存器RCC->CFGR RCC->CFGR |= 0x00000400; //AHBCLK = SysTick, APB2CLK = AHBCLK,APB1CLK = AHBCLK/2 PLL-=2; RCC->CFGR |= PLL<<18; //参考寄存器功能表,0010~4倍,依次增加,最大9倍 RCC->CFGR |= 3<<16; //HSE/2作为PLL的输入 //3.FLASH预存取即时钟配置 //FLASH预存取寄存器FLASH->ACR //注:具体参见《STM32闪存flash编程》,但有一点要注意,系统时钟大于30MHZ后一定需要配置,默认24MHZ后就需要配置 FLASH->ACR |= 0x32; //开启预存取,2个等待周期 //4.PLL使能 //时钟控制寄存器 RCC->CR RCC->CR |= 1<<24; //PLL使能 while(!(RCC->CR>>25)); //判断PLL使能标志位 //5.PLL作为系统时钟 RCC->CFGR | = 0x00000002; //PLL作为系统时钟 while(temp!=0x02) //PLL成功作为系统时钟,标志位 { temp= RCC->CFGR>>2; temp&= 0x03; }
通过上述方式就完成了时钟的一般外设的时钟初始化设置,配置系统时钟50MHZ,APB2外设时钟50MHZ,APB1外设时钟25MHZ,理解了这些,后续程序运行时所花费的时间通过计算即可精确的知晓,这对于整个嵌入式的学习以及之后理解实时操作系统都是很有帮助的。