①HSI是高速内部时钟,RC振荡器,频率为8MHz。
②HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。
HSE/LSE时钟源
③LSI是低速内部时钟,RC振荡器,频率为40kHz。
④LSE是低速外部时钟,接频率为32.768kHz的石英晶体。
⑤PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz。
STM32时钟系统的框图
在我使用的开发板上 OSC_IN 和 OSC_OUT 外接了 8M 晶振

要想使CPU达到最大工作频率,72M,因为 8x9 = 72
所以系统初始化时的设置位:
1:选择 HSE 作为系统时钟
STM32_RCC_CR |=((uint32_t)BIT(16));
uHseRdy = STM32_RCC_BASE;
uHseRdy = STM32_RCC_CR;
2: 等待HSE 稳定:
//wiat until HSE is ready
do{
uHseRdy = STM32_RCC_CR & RCC_CR_HSERDY;
}while(uHseRdy == 0);
3:调整 FALSH 读取速度:
STM32_FLASH_ACR |= FLASH_ACR_PRFTBE;
/* Flash 2 wait state */
STM32_FLASH_ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
STM32_FLASH_ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
4:设置SYSCLK PCLK1 PCLK2
HSE 经选择器然后经过PLL 倍频 产生 PLLCLK , PLLCLK 经选择器 产生SYSCLK, 系统中设置 PLLCLK = 72M 则 SYSCLK = 72M
SYSCLK 的输出三个方向:
I2S2 的时钟
I2S3 的时钟
经预分频器AHB 直接或者间接位系统大部分外围设备提供时钟
/* 以下其实应该涉及到清零的操作,不过系统启动时候默认每位都是0 (偏移地址: 0x04 复位值: 0x0000 0000 见手册上关于 RCC_CFGR 的说明)
所以都使用 | 操作就可以了 */
/* HCLK = SYSCLK BIT[7:4]=0*/
STM32_RCC_CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK BIT[13-11]=0*/
STM32_RCC_CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK/2 BIT[10-8]=1 分频 2 */
STM32_RCC_CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
其他时钟(ADC USB)等到用的时候再设置
5: 设置PLL 时钟(PLLCLK 值)
/* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
STM32_RCC_CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
RCC_CFGR_PLLMULL));
STM32_RCC_CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
6: 时钟参数我们都设置好了,现在可以开启PLL 了,选择并等待 PLL 稳定
/* Enable PLL */
STM32_RCC_CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
do{}while((STM32_RCC_CR & RCC_CR_PLLRDY) == 0);
7: 选择PLL 位系统时钟,并等待稳定
/* Select PLL as system clock source */
STM32_RCC_CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
STM32_RCC_CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((STM32_RCC_CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL)
{
}
经过以上设置以后就我们的CPU 就再 72M 的频率下工作了
一些其他设备的时钟源:
IWDG(看门狗): 使用LSI RC(40kHz)
HSE/128 = 8M/128
RTC通过设置(RCC_BDCR) LSE = 32.768Khz 只要VBAT维持供电,尽管VDD供电被切断,RTC仍继续工作。所以通常选用此种时钟
可以选择三种 LSI RC 40kHz
直接使用PLLCLK 通过设置 RCC_CFGR BIT[22] 来选择时钟频率
USB CLOCK 0: USBCLK = PLLCLK/1.5 1: USBCLK = PLLCLK
所以PLLCLK 只能时 48 或者 72 设置位 72M 时 BIT[22] = 0
APB1 CLOCK APB1 是用来作为外部慢速设备的时钟,最大位 36M 所以 将 RCC_CFGR BIT[10:8]=100 来2 分频 HCLK = 36M
APB2 CLOCK APB2(PCLK2) 是系统位外部快速设备的时钟 最大 72M 所以 RCC_CFGR BIT[13:11] = 000 PCLK2 = HCLK = 72M
SDIO AHB 接口 固定为: HCLK/2 = 36M
ADC Clock 通过设置 RCC_CFGR BIT[15:14] 来设置 00: = PCLK2/2 = 36M 01: = PCLK2/4 = 18M 10:=PCLK2/6=12M 11: = PCLK2/8 = 9M
ADC CLOCK 最大为:14MHz 所以只能选择 10 11
TIMXCLK(2-7) 定时器2-7 的频率依赖 APB1 的分频时钟 如果 APB1 分频 > 1 则 TIMXCLK= APB1CLK*2
APB1 分频 = 1 则 TIMXCLK = APB1CLK 再上面的设置中 APB1 CLOKC = 36M 是 2分频 所以 TIMXCLK = APB1CLK*2 = 72M
定时器 1 和8 依赖 APB2 分分频 如果 APB2 分频 > 1 则 TIMXCLK = APB2CLK *2 ze
TIMXCLK(1和8) 如果APB2 分频 = 1 则 TIMXCLK = APB2CLK 上面设置值中 APB2 CLOCK = 72M 没有分频
所以 TIM1CLK 和 TIME2CLK = 72M
MCO 输出时钟 可选择 4 中频率来源作为其输出的时钟
PLLCLK/2 HSI HSE 以及 SYSCLK