STM32F103学习笔记-16-RCC(第4节)-使用 HSI 配置系统时钟并用 MCO 监控系统时钟
一、实验背景与目的
上一节课中,我们已经学习了如何使用外部高速时钟 HSE(High Speed External)作为系统时钟源,并通过 MCO(Microcontroller Clock Output)输出信号来验证时钟配置是否正确。
本节我们将继续深入学习:
如何使用内部高速时钟 HSI(High Speed Internal)配置系统时钟,并通过 MCO 输出验证系统频率。
二、HSI 的原理回顾
HSI 是 STM32 内部自带的高速 RC 振荡器(通常为 8 MHz),不依赖外部晶振。它启动速度快,但精度略低,一般用于:
节省成本或无外部晶振时;
在调试、测试阶段使用;
或在低功耗快速启动应用中。
HSI 可直接作为系统时钟源,也可以经过 除 2 后作为 PLL 输入源,经倍频后生成更高频率。
例如:
HSI = 8 MHz
HSI / 2 = 4 MHz
若倍频因子 = 16 → 系统时钟 = 4 MHz × 16 = 64 MHz
三、代码分析与实现步骤
1. 头文件 bsp_rcclkconfig.h
#ifndef __BSP_RCCLKCONFIG_H
#define __BSP_RCCLKCONFIG_H#include "stm32f10x.h"void HSE_SetSysClk(uint32_t RCC_PLLMul_x);
void MCO_GPIO_Config(void);
void HSI_SetSysClk(uint32_t RCC_PLLMul_x);#endif
这里声明了三个函数:
HSE_SetSysClk():上节课的外部晶振配置函数。
MCO_GPIO_Config():配置 PA8 为时钟输出引脚。
HSI_SetSysClk():本节新增的函数,用于用 HSI 配置系统时钟。
2. 主函数 main.c
int main(void)
{HSI_SetSysClk(RCC_PLLMul_16); // 使用HSI × 16 = 64MHzMCO_GPIO_Config(); // 配置MCO输出引脚RCC_MCOConfig(RCC_MCO_SYSCLK); // 输出系统时钟到PA8LED_GPIO_Config(); // 初始化LEDwhile(1){LED_G(OFF);Delay(0xFFFFF);LED_G(ON);Delay(0xFFFFF);}
}
程序逻辑讲解:
HSI_SetSysClk()
使用内部时钟 HSI 作为 PLL 输入,倍频后配置系统时钟为目标频率(例:64 MHz)。MCO_GPIO_Config()
配置 PA8 为复用推挽输出,用于输出时钟信号。RCC_MCOConfig(RCC_MCO_SYSCLK)
将系统时钟源(SYSCLK)输出到 MCO 引脚(PA8),以便用示波器测量。LED_GPIO_Config()与循环闪灯
通过 LED 闪烁的频率变化,粗略观察系统时钟的快慢。
3. bsp_rcclkconfig.c 的实现逻辑
void HSI_SetSysClk(uint32_t RCC_PLLMul_x)
{__IO uint32_t HSIStatus;RCC_DeInit(); // 复位RCC寄存器RCC_HSICmd(ENABLE); // 使能HSIHSIStatus = RCC->CR & RCC_CR_HSIRDY; // 判断HSI是否稳定if(HSIStatus == RCC_CR_HSIRDY) // 若稳定则配置系统时钟{FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);FLASH_SetLatency(FLASH_Latency_2);RCC_HCLKConfig(RCC_SYSCLK_Div1);RCC_PCLK1Config(RCC_HCLK_Div2);RCC_PCLK2Config(RCC_HCLK_Div1);RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_x); // HSI/2 × 倍频RCC_PLLCmd(ENABLE);while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); // 等待PLL稳定RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); // 切换系统时钟源while(RCC_GetSYSCLKSource() != 0x08); // 等待切换完成}else{/* 如果HSI启动失败,可以在这里加入错误处理 */}
}
代码逻辑拆解:
| 步骤 | 动作 | 说明 |
|---|---|---|
| ① | RCC_DeInit() | 将 RCC 寄存器恢复到复位状态,防止旧配置干扰。 |
| ② | RCC_HSICmd(ENABLE) | 开启内部 8 MHz RC 振荡器。 |
| ③ | RCC->CR & RCC_CR_HSIRDY | 检查 HSI 是否准备就绪。 |
| ④ | FLASH_SetLatency() | 调整 Flash 等待周期,适应高频访问速度。 |
| ⑤ | RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_x) | 设置 PLL 源为 HSI/2,并指定倍频因子。 |
| ⑥ | RCC_PLLCmd(ENABLE) | 启动 PLL 并等待其锁定(稳定)。 |
| ⑦ | RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK) | 将系统时钟切换到 PLL 输出。 |
| ⑧ | RCC_GetSYSCLKSource() | 验证切换成功。 |
四、使用 MCO 输出验证时钟
1. 配置 GPIO(PA8)
void MCO_GPIO_Config()
{GPIO_InitTypeDef GPIO_InitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);
}
PA8 是 MCO 引脚(可输出 SYSCLK、HSI、HSE、PLLCLK/2 等信号)。
这里配置为复用推挽输出模式,以驱动示波器或外部电路。
2. 输出时钟信号
RCC_MCOConfig(RCC_MCO_SYSCLK);
此函数将 系统时钟(SYSCLK) 输出到 PA8 引脚。
若想输出 HSI,可改为
RCC_MCOConfig(RCC_MCO_HSI);
若想输出 PLLCLK/2,可改为RCC_MCOConfig(RCC_MCO_PLLCLK_Div2)。
五、实验现象与验证
| 配置 | 理论频率 | 实际测量(示波器) | 现象 |
|---|---|---|---|
HSE_SetSysClk(RCC_PLLMul_9) | 72 MHz | ≈ 72 MHz | LED闪烁正常 |
HSI_SetSysClk(RCC_PLLMul_16) | 64 MHz | ≈ 64 MHz | LED闪烁略慢 |
HSI_SetSysClk(RCC_PLLMul_12) | 48 MHz | ≈ 48 MHz | LED闪烁更慢 |
若测得的频率与预期一致,则系统时钟配置成功。
示波器应接地良好,并断开蜂鸣器跳帽(PA8连接蜂鸣器会影响波形)。
六、实验总结
通过本节实验,我们学会了:
如何使用 HSI(内部时钟)通过 PLL 倍频配置系统时钟;
如何通过 MCO 输出验证系统时钟频率;
理解了固件库函数
RCC_HSICmd、RCC_PLLConfig、RCC_MCOConfig的配合使用;掌握了调试与验证时钟系统的基本方法。
