一、时钟树图表
二、时钟详解(结合时钟树)
HSE时钟(72M) HSE:High Speed-External Clock signal,即高速的外部时钟 来源:无源晶振(4-16M),通常使用8M 控制:RCC CR时钟控制寄存器的位16:HSEON控制
HSI时钟 HSI:Low Speed Internal Clock signal,高速的内部时钟 来源:芯片内部,大小为8M,当HSE故障时,系统时钟会自动切换到HSI,直到HSE启动成功。 控制:RCC_CR时钟控制寄存器的位0:HSION控制
锁相环时钟 锁相环时钟:PLLCLK(官方72M,实际64M) 来源:(HSI2、HSE)经过倍频所得。(常用HSE) 控制:CFGR:PLLXTPRE、 PLLMUL 注意:PLL时钟源头使用HIS/2的时候, PLLMUL最大只能是16,这个时候 PLLCLK最大只能是64M,小于ST官方推荐的最大时钟72M。
系统时钟 锁相环时钟:SYSCLK,最高为72M(ST官方推荐的) 来源:HSI、HSE、 PLLCLK。 控制:CFGR:SW 注意:通常的配置是 SYSCLK= PLLCLK=72M
HCLK时钟 HCLK:AHB高速总线时钟,速度最高为72M。为AHB总线的外设提供时钟、为 Cortex系统定时器提供时钟 ( SysTick)、为内核提供时钟(FCLK) AHB:advanced high- performance bus。 来源:系统时钟分频得到,一般设置HCLK= SYSCLK=72M 控制:CFGR:HPRE
PCLK时钟 PCLK1:APB1低速总线时钟,最高为36M。为APB1总线的外设提供时钟。2倍频之后则为APB1总线的定时器2-7提供时钟,最大为72M。 来源:HCLK分频得到,一般配置PCLK1=HCLK/2=36M 控制:RCC CFGR时钟配置寄存器的PPRE1位
PCLK2时钟 PCLK2:APB2高速总线时钟,最高为72M。为APB1总线的外设提供时钟。为APB1总线的定时器1和8提供时钟,最大为72M。 来源:HCLK分频得到,一般配置PCLK1=HCLK=72M 控制:RCC CFGR时钟配置寄存器的PPRE2位
RTC时钟 RTC时钟:为芯片内部的RTC外设提供时钟。 来源:HSE RTG(HSE分频得到)、LSE(外部32.768KHz的晶体提供)、LSI(32KHZ)。 控制:RCC备份域控制寄存器 RCC BDCR:RTCSEL位控制 独立看门狗时钟:TWDGCLK,由LS提供
Mco时钟输出 Mco:microcontroller clock output,微控制器时钟输出引脚,由PA8复用所得。 来源:PLLCLK/2,HSE、HSI、 SYSCLK 控制:CRGR:MCO (自己写时钟配置函数,检测对错,利用Mco输出引脚,通过示波器看波形)
时钟安全系统(CSS) 时钟安全系统可以通过软件被激活。一旦其被激活,时钟监测器将在HSE振荡器启动延迟后被使能,并在HSE时钟关闭后关闭。 如果HSF时鈾发生故障,HSE振荡器被自动关闭,时钟失效事件将被送到高级定时器(TIM1和TIM8)的刹车输入端,并产生时钟安全中断CSS, 允许软件完成营救操作。此CS中断连接到CortexTM-M3的NMI中断(不可屏蔽中断) 注意:一日CSS被激活,并且HSE时钟出现故障,CSS中断就产生,并NMI也自动产生。MM将被不断执行,直到CSS中断挂起位被清除。 因此,在NM的处理程序中必须通过设置时钟中断寄存器( RCC CIR)里的CSSC位来清除CSS中断。 如果HSE振荡器被直接或间接地作为系统时钟,(间接的意思是:它被作为PLL输入时钟,并且PLL时钟被作为系统时钟),时钟故障将导致系统时钟自动切换到HSI振荡器,同时外部HSE振荡器被关闭。 在时钟失效时,如果HSE振荡器时钟(被分频或未被分频)是用作系统时钟的PLL的输 (如果HES出故障,且没有使能CSS,系统时钟切换到HSI(8M低速运行))
HSE=高速外部时钟信号 HSI=高速内部时即信号 LSI=低速内部时钟信号 LSE=低速外部时钟信号
三、 时钟配置思路:
1、使用为外部的高速时钟信号【HSE(8M不分频)】来配置时钟 2、然后进入锁相环时钟时钟源(PLLCLK)–配9倍频—>8*9=72M 3、结果出来的锁相环时钟(PLLCLK)–为72M 4、配置系统时钟(三个选择HSE/PLLCLK/HSI)我们选择锁相环时钟(PLLCLK)为系统时钟(SYSCLK) 5、如果APB1–选择2分频=36M,或APB2–选择1分频 (以上总线配置好了) 6、剩下其它外设使用时配置
四、固件库——系统时钟配置函数
static void SetSysClockTo72(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
do {
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while ((HSEStatus == 0)
&&(StartUpCounter !=HSE_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSERDY) != RESET) {
HSEStatus = (uint32_t)0x01;
} else {
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01) {
FLASH->ACR |= FLASH_ACR_PRFTBE;
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
RCC->CFGR &= (uint32_t)((uint32_t)
~(RCC_CFGR_PLLSRC
| RCC_CFGR_PLLXTPRE
| RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE
| RCC_CFGR_PLLMULL9);
RCC->CR |= RCC_CR_PLLON;
while ((RCC->CR & RCC_CR_PLLRDY) == 0) {
}
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
while ((RCC->CFGR&(uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08){
}
} else {
}
}
|