时钟配置检查报告

时钟配置检查里最容易踩的坑:HSI_DIV4 把波特率误差推到约 8.5%、睡眠模式下外设直接停摆。本文结合 115200 串口与 ADC 实测,逐一验证 HSI / HSI+PLL 三种时钟配置,并给出升到 16MHz 把误差压到 0.5% 以内的优化方案与代码。

2026-07-04
时钟配置MCU系统时钟PLL

嵌入式系统时钟配置检查报告

先交代下这篇的来头。这是我们在一个低功耗采集项目上做的现场时钟排查:设备待机能压到 1.2mA 很漂亮,可代价是系统时钟被放到很低的 HSI_DIV4(4MHz),串口波特率误差一度跑到约 8.5%,睡眠模式下 ADC 和串口还会直接停摆。所以我们把每一路时钟源、分频和串口计算都重新核了一遍,重点看它到底能不能同时满足串口通讯、ADC、比较器这三路功能——结论和优化动作都写在下面。


1. 当前时钟配置分析

1.1 系统时钟配置

配置参数:

串口时钟配置:

1.2 波特率计算

计算公式:


波特率 = PCLK1 / (8 * (2 - OVER8) * BRR)

当前配置:

这里有个绕不开的约束:BRR 必须取整数,所以实际算出来的波特率一定跟目标值有偏差,115200 档下来误差约 8.5%,串口通讯可靠性会受影响。


2. 功能需求验证

2.1 串口通讯功能

串口这边整体可用,但别掉以轻心。波特率生成基本能对上,只是存在误差(算下来约 8.5%);数据传输的可靠性取决于这个误差到底有多大,而无数据丢失则要看中断处理及不及时。真正的隐患有两个:一是波特率误差大了可能导致通讯错位,二是系统一旦进睡眠,串口时钟可能直接停住。

2.2 睡眠模式下的ADC功能

ADC 在正常模式下没问题,采样精度 8 位能满足基本需求,转换速率是 1.5 个周期的采样时间。但在 4MHz 的系统时钟下,这套速率跑起来偏慢;更麻烦的是睡眠模式下 ADC 时钟会停,唤醒后必须重新初始化。

潜在问题:

2.3 睡眠模式下的比较器功能

比较器是这三种外设里状态最好的一个。COMP2 配置成低功耗模式,在睡眠模式下依然能正常做电压比较;中断触发配合上升沿方式,可以在睡梦中把系统唤醒——这一路基本不用操心。

2.4 睡眠模式下的串口通讯

串口睡眠下最纠结。设备睡着的这段时间,串口时钟可能停止,数据接收/发送会停摆;好在串口中断仍能把系统唤醒,但通讯的完整性就取决于唤醒后时钟恢复得够不够快。

潜在问题:


3. PA15控制代码位置

代码位置:

代码实现:


HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);
HAL_Delay(1);
HAL_UART_Transmit(&huart2, pch->TxBuf, pch->TxBufByteCtr, 100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET);
HAL_Delay(1);

功能说明:


4. 测试数据与分析

4.1 时钟配置测试

时钟配置 系统时钟 APB1时钟 串口波特率 波特率误差 通讯可靠性
HSI_DIV4 4MHz 2MHz 115200 ~8.5% 一般
HSI 16MHz 8MHz 115200 ~0.5% 良好
HSI+PLL 32MHz 16MHz 115200 ~0.1% 优秀

4.2 功耗模式测试

功耗模式 电流消耗 ADC功能 比较器功能 串口功能
正常模式 9.1mA 正常 正常 正常
睡眠模式 1.2mA 停止 正常 停止
深度睡眠 0.5mA 停止 停止 停止

4.3 中断响应测试

中断源 正常模式响应时间 睡眠模式唤醒时间 可靠性
串口接收 <1ms ~10ms 良好
比较器 <1ms ~5ms 良好
定时器 <1ms ~8ms 良好

5. 配置建议

5.1 时钟配置优化

推荐配置:

优势:

5.2 睡眠模式优化

推荐策略:

  1. 使用WFI (Wait For Interrupt)模式:
  1. 外设时钟管理:
  1. 中断唤醒配置:

5.3 功能完整性保障

建议措施:

  1. 串口通讯:
  1. ADC功能:
  1. 比较器功能:

6. 结论

6.1 当前配置评估

先说说这套配置做得好的地方。低功耗设计是真省电,正常模式 9.1mA、睡眠只有 1.2mA,基本功能也齐全,PA15 的控制逻辑没毛病。但短板同样明显:波特率误差偏大,睡眠模式下串口和 ADC 都受限,整体响应速度也偏慢。

6.2 优化建议

短期优化:

  1. 提高系统时钟频率至16MHz
  2. 优化串口过采样设置
  3. 改进睡眠模式下的外设管理

长期优化:

  1. 实现动态时钟管理
  2. 优化中断处理机制
  3. 开发更精细的功耗管理策略

6.3 测试建议

  1. 功能测试:
  1. 性能测试:
  1. 可靠性测试:

7. 附录

7.1 时钟配置代码

当前配置:


__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_DIV4;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV2;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

推荐配置:


__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

7.2 串口配置代码

当前配置:


huart2.Init.BaudRate = 115200;
huart2.Init.OverSampling = UART_OVERSAMPLING_8;

推荐配置:


huart2.Init.BaudRate = 115200;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;

7.3 PA15控制代码


// 位于 d:\work\INV-002\CDC\CDC\CUBE\MODBUS\mb.C:35-38
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);
HAL_Delay(1);
HAL_UART_Transmit(&huart2, pch->TxBuf, pch->TxBufByteCtr, 100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET);
HAL_Delay(1);

还想接着看

如果你也在调 MCU 时钟或低功耗采集,下面几篇大概率能续上:

这份检查记录整理自我们的低功耗采集项目。如果你手上的设备也遇到波特率漂、睡眠唤醒丢数据这类问题,欢迎按页尾的方式联系我们。