3. 时钟系统:24MHz晶振、RTC时钟、PLL配置与时钟树

时钟,说白了就是芯片的“心跳”。没有它,CPU没法跑,外设也没法工作。我刚开始做BSP的时候,总觉得时钟配置很简单——不就是找个晶振,配个PLL嘛。结果有一次板子死活起不来,查了三天才发现是时钟树里某个分频器设错了。嗯,从那以后我再也不敢小看时钟系统了。

今天咱们就好好聊聊NXP开发板的时钟系统。我会从硬件原理讲到软件配置,把24MHz晶振、RTC时钟、PLL和时钟树这些知识点串起来。

3.1 24MHz主晶振电路

先看硬件。NXP芯片一般需要两个晶振:一个主晶振,一个RTC晶振。主晶振通常是24MHz,RTC晶振是32.768kHz。

24MHz晶振接在芯片的XTALI和XTALO引脚上。电路很简单,就是晶振加两个负载电容。但这里有个坑——负载电容的值不能随便选。

负载电容计算公式:

CL = (C1 * C2) / (C1 + C2) + Cstray

其中Cstray是PCB走线的寄生电容,一般取3-5pF

我个人习惯用12pF的负载电容。如果晶振要求18pF,那就选两个33pF的电容串起来。我在项目中遇到过有人直接抄参考设计,结果晶振起振不稳定,系统偶尔死机。后来一查,是PCB布局导致寄生电容偏大,晶振频率偏了。

布局建议:

  • 晶振尽量靠近芯片引脚,走线不超过10mm
  • 晶振下方不要走其他信号线
  • 负载电容的地要单独打过孔到地平面

3.2 RTC时钟电路

RTC时钟用的是32.768kHz晶振。为什么选这个频率?因为2^15 = 32768,用15位计数器就能精确分频出1秒的时钟。你想想看,这个设计多巧妙。

RTC晶振的电路和主晶振类似,但功耗要求更严格。因为RTC通常用电池供电,晶振的驱动电流不能太大。NXP芯片内部一般有RTC振荡器,外部只需要接晶振和两个负载电容。

注意:RTC晶振的负载电容通常选6pF或9pF,不要和主晶振搞混了。我曾经见过有人把24MHz的负载电容用在RTC上,结果RTC一天慢好几分钟。

RTC还有一个重要功能——在系统掉电时保持时间。NXP芯片的RTC模块有独立的电源引脚VBAT,接一个纽扣电池或者超级电容。这样主电源断了,RTC还能继续跑。

3.3 PLL配置与时钟树

好了,硬件说完了,咱们看看软件怎么配。NXP的时钟树其实不复杂,但分支多。我画个简化的结构给你看:

24MHz晶振 → OSC → PLL0 → 分频器 → CPU核心时钟
                    → PLL1 → 分频器 → 外设总线时钟
                    → PLL2 → 分频器 → USB、以太网等
32.768kHz → RTC OSC → RTC计数器

PLL的作用就是把低频的晶振信号倍频到高频。比如24MHz的晶振,通过PLL可以倍频到1GHz以上。但要注意,PLL的输出频率不能超过芯片的最大规格。

配置PLL的步骤一般是:

  1. 选择时钟源(内部振荡器还是外部晶振)
  2. 设置PLL的倍频系数和分频系数
  3. 等待PLL锁定(Lock)
  4. 切换系统时钟到PLL输出

代码实现大概是这样的:

// 以NXP i.MX RT系列为例
void clock_init(void)
{
    // 1. 使能24MHz晶振
    OSC_Enable(OSC_24M);
    
    // 2. 配置PLL0:24MHz * 50 = 1200MHz
    PLL_Config(PLL0, 24, 50, 1);
    
    // 3. 等待PLL锁定
    while(!PLL_IsLocked(PLL0));
    
    // 4. 切换系统时钟
    CLOCK_SetSysClock(PLL0_OUT);
}

PLL配置公式:

Fout = Fin * (MFI + MFN / MFD) / PDF

其中:

  • Fin:输入频率(24MHz)
  • MFI:整数倍频系数
  • MFN/MFD:小数倍频系数
  • PDF:预分频系数

这里有个经验——尽量用整数倍频。小数倍频虽然精度高,但PLL的抖动会大一些。我在做音频设备的时候,就因为这个抖动导致音频输出有杂音。后来改成整数倍频,问题就解决了。

3.4 时钟树的分支管理

时钟树不只是给CPU提供时钟,还要给各种外设分配时钟。NXP芯片一般有多个时钟域:

时钟域 典型频率 用途
CPU_CLK 600MHz - 1.2GHz CPU核心
AHB_CLK 100MHz - 200MHz 高速总线(DMA、SRAM等)
APB_CLK 25MHz - 50MHz 低速外设(UART、I2C、SPI等)
USB_CLK 480MHz USB控制器
ENET_CLK 125MHz 以太网

配置时钟树时,要特别注意外设的时钟频率上限。比如UART的时钟不能超过芯片规格,否则通信会出错。我建议你先看芯片手册的“Clock Tree”章节,把每个外设的时钟源和分频系数搞清楚。

调试技巧:如果某个外设不工作,先检查它的时钟有没有开启。NXP芯片的CCM(Clock Controller Module)里有个寄存器叫CCGRx,专门控制外设时钟的使能。很多新手都栽在这个坑里。

3.5 低功耗模式下的时钟管理

最后聊聊低功耗。NXP芯片支持多种低功耗模式,比如Run、Wait、Stop、Standby。不同模式下,时钟的配置也不同。

  • Run模式:所有时钟都开启,性能最高
  • Wait模式:CPU时钟关闭,外设时钟保持
  • Stop模式:大部分时钟关闭,只有RTC和唤醒逻辑工作
  • Standby模式:几乎全部关闭,只有RTC保持

我在做物联网设备时,要求待机功耗低于10μA。当时就是靠Stop模式加上RTC定时唤醒实现的。注意,进入低功耗前要先把PLL切换到内部振荡器,否则PLL在低功耗下会失锁。

避坑指南:我曾经在进入Stop模式前忘了关闭PLL,结果芯片功耗比预期高了10倍。后来查手册才发现,PLL在Stop模式下虽然输出被切断,但内部还在工作,功耗没降下来。正确的做法是先切到内部振荡器,再关PLL,最后进Stop。

好了,时钟系统就聊到这儿。总结一下:24MHz晶振是基础,RTC负责掉电保持,PLL负责倍频,时钟树负责分配。每个环节都有坑,但只要按部就班地配,就不会出大问题。下一章咱们讲GPIO和中断系统,到时候再聊。