在线调试时想实时看系统时钟是否正常,但代码里没开 MCO、重新烧录又会丢失现场、复现不了问题?
ST 官方 LAT1255 应用笔记给出了最硬核的解决办法:程序暂停时,直接在调试器里改寄存器,临时把 PA8 配置成 MCO 时钟输出,不用改代码、不用重新编译、不破坏现场,立刻就能用示波器抓到 SYSCLK、HSI、HSE、PLL 等内部时钟。
本文把完整操作步骤、寄存器配置、GPIO 设置一次性讲透,是嵌入式调试必备的高阶技巧。
资料获取:【应用笔记】LAT1255 直接修改寄存器来输出内部时钟的方法
1. 适用场景:为什么要在线改寄存器开 MCO?
- 问题偶发难复现,烧录程序就丢失现场
- 想确认SYSCLK、PLL、LSE、HSI是否真的起振
- 没有预留 MCO 引脚,临时借用 PA8测时钟
- 排查死机、跑飞、时钟切换失败等底层问题
优势:不修改工程、不重新烧录、不影响当前运行现场。
2. 核心原理:两步就能输出时钟
- 配置 RCC_CFGR 寄存器:选择要输出的时钟源 + 分频
- 配置 PA8 为复用功能 AF0(MCO),硬件自动输出时钟
以 STM32G474 为例,MCO 默认输出引脚:PA8。
3. 调试器在线配置步骤(暂停时直接操作)
3.1 先开 GPIOA 时钟(必须第一步)
在调试寄存器窗口找到:
- RCC_AHB2ENR
- 将 GPIOAEN(Bit0) 置 1→ 使能 GPIOA 时钟,否则配置无效。
3.2 配置 RCC_CFGR 输出目标时钟
找到寄存器 RCC_CFGR,重点配置两位:
- MCOSEL[27:24]:时钟源选择
- 0001:输出 SYSCLK(最常用)
- 0011:输出 HSI16
- 0100:输出 HSE
- 0101:输出 PLL
- MCOPRE[30:28]:分频(建议先设不分频 000)
写入后,MCO 时钟源选择完成。
3.3 配置 PA8 为 MCO 复用功能
按以下顺序修改 GPIOA 寄存器:
- GPIOA_MODER:MODER8 设为 10(复用功能)
- GPIOA_OTYPER:OT8 设为 0(推挽输出)
- GPIOA_OSPEEDR:OSPEED8 设为 10 / 11(高速 / 超高速)
- GPIOA_PUPDR:PUPD8 设为 01(上拉)
- GPIOA_AFRH:AFSEL8 设为 0000(AF0,MCO 功能)
配置完成后,PA8 会立即输出内部时钟,示波器可直接测量。
4. 寄存器配置速查表(直接照着填)
| 寄存器 | 位 | 数值 | 含义 |
|---|---|---|---|
| RCC_AHB2ENR | Bit0 | 1 | 开 GPIOA 时钟 |
| RCC_CFGR | MCOSEL[27:24] | 0001 | 输出 SYSCLK |
| RCC_CFGR | MCOPRE[30:28] | 000 | 不分频 |
| GPIOA_MODER | MODER8 | 10 | 复用功能 |
| GPIOA_OTYPER | OT8 | 0 | 推挽 |
| GPIOA_OSPEEDR | OSPEED8 | 10 | 高速 |
| GPIOA_PUPDR | PUPD8 | 01 | 上拉 |
| GPIOA_AFRH | AFSEL8 | 0000 | AF0=MCO |
5. 注意事项(LAT1255 重点强调)
LAT1255 提供的在线修改寄存器输出 MCO 时钟,是 STM32 调试里成本最低、效率最高的神技:
- 不用改工程
- 不用重编译
- 不破坏现场
- 秒出时钟波形
遇到时钟不稳、死机、偶发异常,用这招能快速定位是不是时钟问题。
阅读全文
266