高速外部时钟信号 (HSE)

当使用有源晶振时,时钟从 OSC_IN 引脚进入,OSC_OUT 引脚悬空,
当选用无源晶振时,时钟从OSC_IN 和 OSC_OUT 进入,并且要配谐振电容。
高速内部时钟信号(HSI)
HSI 时钟信号由内部 16 MHz RC 振荡器生成,可直接用作系统时钟,或者用作 PLL 输入。
PLL
PLL 的主要作用是对时钟进行倍频,然后把时钟输出到各个功能部件。PLL 有两个,一个是主 PLL,另外一个是专用的 PLLI2S,他们均由 HSE 或者 HSI 提供时钟输入信号。
主 PLL (PLL) 由 HSE 或 HSI 振荡器提供时钟信号,并具有两个不同的输出时钟:
- 第一个输出用于生成高速系统时钟(最高达 168 MHz)
- 第二个输出用于生成 USB OTG FS 的时钟 (48 MHz)、随机数发生器的时钟 (48 MHz) 和 SDIO 时钟 (48 MHz)。

专用 PLL (PLLI2S) 用于生成精确时钟,从而在 I2S 接口实现高品质音频性能。
低速外部时钟信号(LSE)
LSE 晶振是 32.768 kHz 低速外部 (LSE) 晶振或陶瓷谐振器,可作为实时时钟外设 (RTC) 的时钟源来提供时钟/日历或其它定时功能,具有功耗低且精度高的优点。
低速内部时钟信号(LSI)
LSI RC 可作为低功耗时钟源在停机和待机模式下保持运行,供独立看门狗 (IWDG) 和自动唤醒单元 (AWU) 使用。时钟频率在 32 kHz 左右。
时钟的输出功能
RCC
设置系统时钟 SYSCLK、设置 AHB 分频因子(决定 HCLK 等于多少)、设置 APB2 分频因子(决定 PCLK2 等于多少)、设置 APB1 分频因子(决定 PCLK1 等于多少)、设置各个外设的分频因子;控制 AHB、APB2 和 APB1 这三条总线时钟的开启、控制每个外设的时钟的开启。对于 SYSCLK、HCLK、PCLK2、PCLK1 这四个时钟的配置一般是:HCLK = SYSCLK=PLLCLK ,PCLK2=HCLK/2 ,PCLK1=HCLK/4 。
HCLK = SYSCLK=PLLCLK = 168M(F407)
PCLK2=HCLK/2 = 84M(F407)
PCLK1=HCLK/4 = 42M(F407)
系统时钟 (SYSCLK) 选择
系统时钟来源可以是:HSI、PLLCLK、HSE,具体的由时钟配置寄存器 RCC_CFGR 的 SW 位配置。
在系统复位后,默认系统时钟为 HSI。在直接使用 HSI 或者通过 PLL 使用时钟源来作为系统时钟时,该时钟源无法停止。
只有在目标时钟源已就绪时(时钟在启动延迟或 PLL 锁相后稳定时),才可从一个时钟源切换到另一个。如果选择尚未就绪的时钟源,则切换在该时钟源就绪时才会进行。
HCLK总线时钟
系统时钟 SYSCLK 经过 AHB 预分频器分频之后得到时钟叫 AHB 总线时钟,即 HCLK,分频因子可以是:[1, 2, 4,8,16,64,128,256,512],具体的由时钟配置寄存器 RCC_CFGR 的 HPRE 位设置。
片上大部分外设的时钟都是经过 HCLK 分频得到,至于 AHB 总线上的外设的时钟设置为多少,得等到我们使用该外设的时候才设置,我们这里只需粗线条的设置好 APB 的时钟即可。我们这里设置为 1 分频,即 HCLK=SYSCLK=168M F407。
APB2 总线时钟 PCLK2
APB2 总线时钟 PCLK2 由 HCLK 经过高速 APB2 预分频器得到,分频因子可以是:[1,2,4,8,16],具体由时钟配置寄存器 RCC_CFGR 的 PPRE2 位设置。
PCLK2 属于高速的总线时钟,片上高速的外设就挂载到这条总线上,比如全部的 GPIO、USART1、SPI1 等。
至于 APB2 总线上的外设的时钟设置为多少,得等到我们使用该外设的时候才设置,我们这里只需粗线条的设置好 APB2 的时钟即可。我们这里设置为 2 分频,即 PCLK2 = HCLK /2= 84M(F407)。
APB1 总线时钟 PCLK1
APB1 总线时钟 PCLK1 由 HCLK 经过低速 APB 预分频器得到,分频因子可以是:[1,2,4,8,16],具体由时钟配置寄存器 RCC_CFGR 的 PPRE1 位设置。PCLK1 属于低速的总线时钟,最高为 42M (F407)片上低速的外设就挂载到这条总线上,比如 USART2/3/4/5、SPI2/3,I2C1/2等。
我们这里设置为 4 分频,即 PCLK1 = HCLK/4 = 42M(F407)
配置系统时钟库函数
/*** @brief 系统时钟配置* System Clock source = PLL (HSE)* SYSCLK(Hz) = 168000000* HCLK(Hz) = 168000000* AHB Prescaler = 1* APB1 Prescaler = 4* APB2 Prescaler = 2* HSE Frequency(Hz) = 25000000* PLL_M = 25* PLL_N = 336* PLL_P = 2* PLL_Q = 4* VDD(V) = 3.3* Main regulator output voltage = Scale1 mode* Flash Latency(WS) = 5* @param 无* @retval 无*/static void SystemClock_Config(void){RCC_ClkInitTypeDef RCC_ClkInitStruct;RCC_OscInitTypeDef RCC_OscInitStruct;HAL_StatusTypeDef ret = HAL_OK;/* 使能HSE,配置HSE为PLL的时钟源,配置PLL的各种分频因子M N P Q* PLLCLK = HSE/M*N/P = 12M / 25 *360 / 2 = 180M*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = 25;RCC_OscInitStruct.PLL.PLLN = 336;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;RCC_OscInitStruct.PLL.PLLQ = 4;ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);if( ret != HAL_OK){while(1) {}}/* 选择PLLCLK作为SYSCLK,并配置 HCLK, PCLK1 and PCLK2 的时钟分频因子* SYSCLK = PLLCLK = 168M* HCLK = SYSCLK / 1 = 168M* PCLK2 = SYSCLK / 2 = 84M* PCLK1 = SYSCLK / 4 = 42M*/RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;ret =HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);if( ret != HAL_OK){while(1) {}}}
使用HSE
/** 使用HSE时,设置系统时钟的步骤* 1、开启HSE ,并等待 HSE 稳定* 2、设置 AHB、APB2、APB1的预分频因子* 3、设置PLL的时钟来源* 设置VCO输入时钟 分频因子 m* 设置VCO输出时钟 倍频因子 n* 设置PLLCLK时钟分频因子 p* 设置OTG FS,SDIO,RNG时钟分频因子 q* 4、开启PLL,并等待PLL稳定* 5、把PLLCK切换为系统时钟SYSCLK* 6、读取时钟切换状态位,确保PLLCLK被选为系统时钟*//** m: VCO输入时钟 分频因子,取值2~63* n: VCO输出时钟 倍频因子,取值50~432* p: PLLCLK时钟分频因子 ,取值2,4,6,8* q: OTG FS,SDIO,RNG时钟分频因子,取值4~15* 函数调用举例,使用HSE设置时钟* SYSCLK=HCLK=168MHz,PCLK2=HCLK/2=84MHz,PCLK1=HCLK/4=42MHz* HSE_SetSysClock(25, 336, 2, 7);* 25M / 25 * 336 /2 = 168 M* HSE作为时钟来源,经过PLL倍频作为系统时钟,这是通常的做法*/void HSE_SetSysClock(uint32_t m, uint32_t n, uint32_t p, uint32_t q){RCC_ClkInitTypeDef RCC_ClkInitStruct;RCC_OscInitTypeDef RCC_OscInitStruct;/* Enable Power Control clock */__HAL_RCC_PWR_CLK_ENABLE();/* The voltage scaling allows optimizing the power consumption whenthe device is clocked below the maximum system frequency, to updatethe voltage scaling value regarding system frequency refer to productdatasheet. */__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);/* Enable HSE Oscillator and activate PLL with HSE as source */RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = 25;RCC_OscInitStruct.PLL.PLLN = 336;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;RCC_OscInitStruct.PLL.PLLQ = 7;if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){while(1) {};}/* Select PLL as system clock source and configure the HCLK,PCLK1 and PCLK2 clocks dividers */RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK |RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK){while(1) {};}/* STM32F405x/407x/415x/417x Revision Z devices: prefetch is supported */if (HAL_GetREVID() == 0x1001){/* Enable the Flash prefetch */__HAL_FLASH_PREFETCH_BUFFER_ENABLE();}}
使用HSI
/** 使用HSI时,设置系统时钟的步骤* 1、开启HSI ,并等待 HSI 稳定* 2、设置 AHB、APB2、APB1的预分频因子* 3、设置PLL的时钟来源* 设置VCO输入时钟 分频因子 m* 设置VCO输出时钟 倍频因子 n* 设置PLLCLK时钟分频因子 p* 设置OTG FS,SDIO,RNG时钟分频因子 q* 4、开启PLL,并等待PLL稳定* 5、把PLLCK切换为系统时钟SYSCLK* 6、读取时钟切换状态位,确保PLLCLK被选为系统时钟*//** m: VCO输入时钟 分频因子,取值2~63* n: VCO输出时钟 倍频因子,取值50~432* p: PLLCLK时钟分频因子 ,取值2,4,6,8* q: OTG FS,SDIO,RNG时钟分频因子,取值4~15* 函数调用举例,使用HSE设置时钟* SYSCLK=HCLK=168MHz,PCLK2=HCLK/2=84MHz,PCLK1=HCLK/4=42MHz* HSE_SetSysClock(16, 336, 2, 7);*16M / 16 * 226 / 2 = 168M* HSE作为时钟来源,经过PLL倍频作为系统时钟,这是通常的做法*/void HSI_SetSysClock(uint32_t m, uint32_t n, uint32_t p, uint32_t q){RCC_ClkInitTypeDef RCC_ClkInitStruct;RCC_OscInitTypeDef RCC_OscInitStruct;/* Enable Power Control clock */__HAL_RCC_PWR_CLK_ENABLE();/* The voltage scaling allows optimizing the power consumptionwhen the device is clocked below the maximum system frequency,to update the voltage scaling value regarding systemfrequency refer toproduct datasheet. */__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);/* Enable HSE Oscillator and activate PLL with HSE as source */RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;RCC_OscInitStruct.PLL.PLLM = 16;RCC_OscInitStruct.PLL.PLLN = 336;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;RCC_OscInitStruct.PLL.PLLQ = 7;while(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){while(1) {};}/* Select PLL as system clock source and configure the HCLK,PCLK1 and PCLK2 clocks dividers */RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK){while(1) {};}/* STM32F405x/407x/415x/417x Revision Z devices: prefetch is supported */if (HAL_GetREVID() == 0x1001){/* Enable the Flash prefetch */__HAL_FLASH_PREFETCH_BUFFER_ENABLE();}}

