
1. 项目概述在嵌入式开发里时钟配置是项目启动后要做的第一件事也是最容易让人“踩坑”的地方。时钟就像是整个微控制器MCU系统的心跳它的频率和稳定性直接决定了CPU跑多快、外设工作是否正常、功耗能降到多低甚至ADC采样的精度。很多新手工程师拿到芯片后照着例程配个时钟就跑起来了但一旦遇到功耗超标、通信不稳定或者定时不准的问题往往就束手无策根源常常就在时钟配置的细节里。今天我们就以Freescale现NXP的MC9S08QE32这款经典的8位MCU为例把它内部时钟源ICS模块掰开揉碎了讲清楚。这个ICS模块麻雀虽小五脏俱全它集成了一个频率锁定环FLL、内部参考时钟、外部时钟接口以及灵活的分频和模式切换机制。理解它你不仅能搞定QE32对NXP其他HCS08系列甚至更现代的Kinetis、LPC系列MCU的时钟系统也能触类旁通。我会结合手册里的原理加上我这些年调试这类芯片的实际经验从为什么需要这么复杂的时钟系统开始一步步带你理解每个寄存器位的作用最后给出几种典型应用场景下的配置“配方”和避坑指南。无论你是正在评估这款芯片还是已经用上了但总觉得时钟配置有点“玄学”这篇文章都能帮你把思路理清。2. ICS模块核心架构与工作原理拆解MC9S08QE32的ICS模块其设计目标是在单一模块内提供高度灵活、可靠且低功耗的时钟解决方案。它不像一些高端ARM MCU那样拥有多个独立的PLL和时钟树而是通过一个核心的FLL和巧妙的路径选择逻辑实现了七种不同的工作模式以满足从全速运行到深度睡眠的各种需求。2.1 频率锁定环FLL的核心作用首先得明白FLL和更常见的PLL锁相环的区别。PLL锁定的是相位通过相位比较器调整压控振荡器VCO的频率直到其输出与参考时钟的相位同步。而FLL顾名思义锁定的是频率。它内部有一个数字控制器通过计算参考时钟周期内DCO数控振荡器的脉冲数来动态调整DCO的频率使其输出频率稳定在FLL输出频率 参考时钟频率 × FLL倍频因子这个关系上。在MC9S08QE32的ICS中FLL的倍频因子不是直接可配的而是由DRSDCO范围选择和DMX3232.768kHz参考时钟最大频率优化这两个位联合决定的。手册中的表11-7是关键DRSDMX32参考频率范围 (kHz)FLL倍频因子DCO输出范围 (MHz)00031.25 - 39.062551216 - 2000132.768 (固定)608~19.9201031.25 - 39.0625102432 - 4001132.768 (固定)1216~39.8510031.25 - 39.0625153648 - 6010132.768 (固定)1824~59.77注意这里的“参考频率”是指输入到FLL的时钟频率。如果使用外部晶振比如常见的4MHz或8MHz你不能直接把它喂给FLL。必须通过RDIV分频器将其分频到31.25kHz到39.0625kHz这个狭窄的范围内FLL才能正常工作。这是很多新手容易忽略的一点直接配置会导致FLL无法锁定系统时钟跑飞。FLL的优势在于其数字特性使其对噪声和电源波动不那么敏感并且在芯片制造工艺偏差下也能通过微调TRIM和FTRIM保持较好的精度。它的锁定时间通常比模拟PLL要短这对于需要快速唤醒的低功耗应用是个优点。2.2 时钟路径与模式选择逻辑ICS模块的时钟路径可以简化为一个选择器网络。理解这个网络是灵活配置时钟的关键。其核心逻辑围绕三个选择参考时钟选择 (IREFS)决定FLL的参考时钟是来自内部大约31.25kHz~39kHz的IRC内部参考时钟还是来自外部经过分频的时钟OSCOUT经过RDIV分频。系统时钟源选择 (CLKS)决定最终输出给系统总线ICSOUT的时钟是来自FLL的输出还是直接来自内部参考时钟ICSIRCLK或外部参考时钟ICSERCLK。这就是“Engaged”使用FLL和“Bypassed”旁路FLL模式的区别。低功耗控制 (LP)在Bypassed模式下决定是否彻底关闭FLL以节省功耗。关闭后ICSLCLK用于BDC调试的时钟将不可用。这三点组合起来就形成了手册中描述的七种模式。我习惯用一个更直观的表格来归纳它们的区别和用途模式CLKSIREFSLP (在Bypass模式下)FLL状态系统时钟源典型应用场景FEI001-启用锁定内部时钟FLL输出上电默认模式无需外部元件中等精度全速运行FEE000-启用锁定外部时钟FLL输出需要高精度时钟如USB、高精度定时使用外部晶振FBI0110启用但被旁路内部参考时钟需要内部时钟的低速运行同时保持FLL预热以便快速切换到FEIFBILP0111禁用内部参考时钟最低功耗运行模式仅需内部时钟用于待机或低功耗任务FBE1000启用但被旁路外部参考时钟需要外部时钟的低速运行同时保持FLL预热以便快速切换到FEEFBELP1001禁用外部参考时钟需要外部时钟精度的低功耗运行如RTC计时STOP---禁用无深度睡眠模式可选择保留内部或外部参考时钟供唤醒用2.3 关键时钟信号详解除了主系统时钟ICSOUTICS模块还提供几个重要的派生时钟用于特定用途ICSIRCLK内部参考时钟输出。当IRCLKEN1时这个大约31-39kHz的时钟信号可以被其他模块如定时器、看门狗使用。它的频率可以通过ICSTRM寄存器微调。ICSERCLK外部参考时钟输出。当ERCLKEN1时外部晶振或输入时钟经过RDIV分频前可以直接输出给其他模块使用。ICSFFCLK固定频率时钟。这是FLL的参考时钟即经过RDIV分频后的时钟的输出。手册特别强调其频率必须不高于ICSOUT频率的1/4才有效。这个时钟通常用于需要与总线时钟异步的低速外设。ICSLCLK本地时钟。它是低范围DCO输出时钟的二分频。这个时钟专门用于后台调试控制器BDC。在FBILP和FBELP这两种低功耗模式下由于FLL被禁用ICSLCLK也随之消失这意味着在这些模式下无法进行后台调试。这是一个重要的调试约束条件。理解这些时钟信号的来源和用途能帮助你在设计低功耗状态机或调试复杂外设时序时做出正确的选择。3. 寄存器配置深度解析与实操步骤看懂了原理我们就要动手配置了。MC9S08QE32的ICS模块主要通过四个寄存器控制ICSC1,ICSC2,ICSTRM,ICSSC。我会逐一拆解每个关键位并解释配置时的“为什么”。3.1 控制寄存器1 (ICSC1) – 模式与参考时钟选择ICSC1寄存器是模式切换的“总开关”。位域名称功能描述与配置要点7:6CLKS时钟源选择。这是切工作模式的首要操作位。•00: 选择FLL输出进入Engaged模式。•01: 选择内部参考时钟进入Bypassed Internal模式。•10: 选择外部参考时钟进入Bypassed External模式。•11: 保留。5:3RDIV参考分频器。仅在外部参考时钟路径上生效。用于将外部晶振频率分频至FLL要求的31.25-39.0625 kHz范围。计算公式F_ref_input F_osc / (分频因子)。分频因子取决于RANGE位见下表。务必确保计算结果在范围内否则FLL无法稳定锁定。2IREFS内部参考选择。决定FLL锁定的参考源。•1: FLL使用内部参考时钟。•0: FLL使用外部参考时钟需正确配置RDIV。1IRCLKEN内部参考时钟输出使能。设为1时ICSIRCLK信号有效可供其他模块使用。0IREFSTEN内部参考时钟在Stop模式使能。如果想在Stop模式下保持内部时钟运行以实现快速唤醒需将此位和IRCLKEN同时置1。RDIV分频因子详解这个表必须会查。RANGE位在ICSC2寄存器中它定义了外部振荡器的工作频率范围。RDIV值RANGE0 (低频: 31.25kHz~38.4kHz)RANGE1 (高频: 1MHz~16MHz)0分频因子 1分频因子 321分频因子 2分频因子 642分频因子 4分频因子 1283分频因子 8分频因子 2564分频因子 16分频因子 5125分频因子 32分频因子 10246分频因子 64保留7分频因子 128保留实操示例1配置一个8MHz外部晶振作为参考时钟假设我们使用一个8MHz的晶振并希望FLL以其为参考。因为8MHz属于1MHz~16MHz范围所以设置ICSC2.RANGE 1。计算RDIV值我们需要F_ref_input在31.25k~39.0625k之间。8MHz / 256 31.25kHz刚好在范围下限。8MHz / 128 62.5kHz就超了。因此RDIV应配置为3对应分频因子256。所以ICSC1.RDIV 3。3.2 控制寄存器2 (ICSC2) – 总线分频与外部振荡器配置ICSC2寄存器主要负责输出分频和外部硬件连接配置。位域名称功能描述与配置要点7:6BDIV总线频率分频器。这是最终决定你芯片跑多快的“档位”。它直接对CLKS选择的时钟源进行分频得到系统总线时钟ICSOUT。•00: 1分频。•01: 2分频复位默认值。•10: 4分频。•11: 8分频。重要ICSOUT频率不能超过芯片手册规定的最大总线频率对于MC9S08QE32通常是20MHz或40MHz具体看型号后缀。5RANGE外部振荡器频率范围选择。根据你焊接在板子上的晶振或陶瓷谐振器的标称频率来选择。•1: 高频范围 (1 MHz 至 16 MHz)。•0: 低频范围 (31.25 kHz 至 38.4 kHz)。选错了会导致振荡器不起振或工作不稳定。4HGO高增益振荡器模式选择。这决定了振荡器电路的驱动强度。•1: 高增益模式。驱动能力强适用于驱动陶瓷谐振器或长走线、高负载电容的晶体。功耗更高。•0: 低功耗模式。驱动能力弱适用于标准的、负载电容匹配好的晶体。功耗更低。经验法则对于常见的32.768kHz手表晶振或小尺寸MHz级晶体通常用低功耗模式(0)即可。如果发现晶振启动困难或在低温下停振可以尝试切换到高增益模式(1)。3LP低功耗选择。在FLL旁路模式(FBI, FBE)下决定是否关闭FLL。•1: 在FBI/FBE模式下关闭FLL即进入FBILP/FBELP模式。•0: 在FBI/FBE模式下保持FLL开启功耗较高但切换回FEI/FEE模式时无需重新锁定。2EREFS外部参考源选择。选择外部时钟的来源。•1: 使用外部晶体/谐振器需要连接XTAL/EXTAL引脚。•0: 使用外部时钟源直接从EXTAL引脚输入方波时钟信号XTAL引脚悬空。1ERCLKEN外部参考时钟输出使能。设为1时ICSERCLK信号有效。0EREFSTEN外部参考时钟在Stop模式使能。与IREFSTEN类似用于在Stop模式下保持外部振荡器运行。3.3 状态与控制寄存器 (ICSSC) – 微调与状态监控ICSSC寄存器混合了状态位和精细控制位。位域名称功能描述与配置要点7:6DRSDCO范围选择。这是改变FLL输出频率范围即倍频因子的关键。写入DRS后需要读取DRST来确认切换是否完成。在LP1低功耗模式时对此位的写入无效。5DMX3232.768 kHz参考时钟最大频率优化。这是一个非常实用的位。当你使用一个精确的32.768kHz手表晶振作为外部参考时将此位置1ICS模块会自动调整内部参数使FLL输出频率达到该DCO范围下的理论最大值见之前的表11-7从而获得最高的系统时钟频率。如果用的不是32.768kHz此位必须清零。4IREFST内部参考状态只读。反映当前FLL实际使用的参考源。由于时钟域同步在写入IREFS后需要等待几个周期再读取此位以确认切换完成。3:2CLKST时钟模式状态只读。反映当前系统时钟的实际来源。同样在写入CLKS后应查询此位以确认模式切换成功。1OSCINIT振荡器初始化完成标志只读。当使用外部晶体(EREFS1)且使能后(ERCLKEN1或处于FEE/FBE/FBELP模式)硬件会置位此位表明外部振荡器已起振稳定。在代码中切换至依赖外部时钟的模式前应轮询此位直到其为1这是一个关键的安全操作。0FTRIM内部参考时钟精细微调。这是对ICSTRM寄存器粗调的补充提供最小步进的频率调整。3.4 完整配置流程与代码示例下面我将给出一个从芯片复位开始配置到常见工作模式的完整流程和代码片段以C语言为例假设使用常见的8位MCU开发环境如CodeWarrior或IAR Embedded Workbench。场景使用8MHz外部晶振目标系统总线频率为40MHz在DRS01 DMX320时FLL输出约40MHz经BDIV1分频/** * brief 初始化ICS模块配置为FLL Engaged External (FEE)模式使用8MHz外部晶振输出40MHz总线时钟。 * note 此函数应在系统初始化早期调用配置时钟前确保芯片供电稳定。 */ void ICS_Init_FEE_40MHz(void) { // 1. 首先确保切换到默认的FEI模式如果之前被改过这是一个好习惯 // CLKS00, IREFS1 即FEI模式 ICSC1 0x04; // CLKS00, RDIV0, IREFS1, IRCLKEN0, IREFSTEN0 // 2. 配置外部振荡器硬件相关参数 (ICSC2) // BDIV先保持默认的2分频01等最终频率稳定后再调整 // RANGE1 (8MHz属于高频范围) // HGO0 (假设使用标准晶体低功耗模式) // LP0 (FLL在旁路模式不关闭) // EREFS1 (使用外部晶体) // ERCLKEN1 (使能外部参考时钟输出可选) // EREFSTEN0 (Stop模式关闭外部振荡器以省电) ICSC2 0x66; // 二进制 0110 0110 // 3. 配置参考分频RDIV // 对于8MHz晶振RANGE1需要分频到31.25k~39.0625k // 8MHz / 256 31.25kHz - RDIV 3 // 更新ICSC1但保持CLKS00, IREFS1 (仍在FEI模式) ICSC1 (ICSC1 0xC7) | (0x3 3); // 清零RDIV位域(bit5-3)然后设置为3 // 4. 等待外部振荡器稳定 // 轮询ICSSC.OSCINIT位直到其为1。这是一个关键等待 while(!(ICSSC 0x02)); // 等待OSCINIT 1 // 5. 切换到FEE模式 // 将ICSC1.IREFS改为0选择外部参考时钟。CLKS保持00。 ICSC1 ~0x04; // 清零IREFS位(bit2) // 6. 可选等待时钟状态稳定 // 读取ICSSC.CLKST确认已切换到FEE模式 (CLKST应为00) // while((ICSSC 0x0C) ! 0x00); // 检查CLKST位(bit3:2) // 7. 配置FLL到目标频率范围 (DRS01, 中范围目标~40MHz) // 同时因为用的不是32.768kHzDMX32必须为0 ICSSC (ICSSC 0x3F) | (0x1 6); // 设置DRS01保持DMX320 // 8. 可选等待DCO范围切换完成 // while((ICSSC 0xC0) ! 0x40); // 等待DRST变为01 // 9. 最后调整总线分频器BDIV以获得最终的系统频率 // 当前FLL输出约为 31.25kHz * 1024 32MHz。我们需要40MHz所以需要提高FLL参考频率。 // 但注意我们之前RDIV3分频后是31.25kHz这是FLL输入的下限。 // 要得到40MHz需要FLL输入为 40MHz / 1024 ≈ 39.0625kHz。 // 重新计算RDIV: 8MHz / 39.0625kHz ≈ 204.8最接近的分频因子是256 (RDIV3)或128 (RDIV2? 查表RANGE1时RDIV2对应128分频)。 // 8MHz / 128 62.5kHz这超出了FLL输入范围(31.25k-39.0625k)所以无法直接用FLL从8MHz晶振产生精确的40MHz。 // 因此我们只能使用FLL的最大输出31.25kHz * 1024 32MHz。 // 如果我们希望总线时钟是40MHz需要选择更高的DCO范围(DRS10)和更低的BDIV。 // 让我们选择DRS10 (高范围)倍频因子1536。 // FLL输出 31.25kHz * 1536 48MHz。 // 然后设置BDIV01 (2分频)得到总线时钟 48MHz / 2 24MHz。或者BDIV00 (1分频)得到48MHz需确认芯片支持。 // 可见时钟配置需要根据可用晶振和芯片支持频率反复权衡。 // 假设我们最终目标就是32MHz总线时钟FLL输出直接使用 // 设置BDIV00 (1分频) ICSC2 (ICSC2 0x3F) | (0x0 6); // 设置BDIV00 // 10. 微调内部参考时钟如果使用FEI/FBI模式时需要 // 从Flash的特定位置通常是0xFFAF读取工厂校准值并写入ICSTRM // 这能保证内部时钟频率相对准确 // ICSTRM *(unsigned char volatile *)(0xFFAF); }重要提示上面的代码示例第9步揭示了一个关键点——不是所有期望的系统频率都能通过任意晶振直接合成。你必须根据晶振频率、可用的RDIV分频因子、DRS决定的FLL倍频因子以及BDIV分频比进行反复计算和权衡。通常需要制作一个计算表格来寻找最优解。4. 低功耗模式下的时钟管理实战MC9S08QE32的ICS模块在低功耗方面设计得很细致。不同的运行模式和Stop模式下的时钟行为是实现超低功耗系统的关键。4.1 运行模式下的功耗权衡七种工作模式本质上是在性能、精度和功耗之间做选择FEI模式功耗和精度折中。无需外部元件FLL锁定内部参考时钟频率精度一般通常±2%以内适合大多数对成本敏感且对时钟精度要求不苛刻的应用。FEE模式精度优先。使用外部晶振可获得很高的频率精度和稳定性晶振精度通常为±10~50ppm功耗比FEI略高因为外部振荡器工作适合需要精确时序或通信如UART、I2C的应用。FBI/FBE模式性能与快速唤醒的平衡。系统直接使用参考时钟内部或外部频率低功耗较低。但FLL仍然在运行并锁定消耗着额外的功耗。这样做的唯一目的是为了在需要时能极快地几个时钟周期内切换回FEI/FEE全速模式因为FLL已经处于锁定状态。如果不需要快速唤醒应使用FBILP/FBELP。FBILP/FBELP模式功耗优先。FLL被完全关闭系统仅运行在低频的参考时钟下功耗最低。从这些模式切换回FEI/FEE模式时需要等待FLL重新锁定的时间tAquire具体时间见芯片数据手册通常在毫秒级。模式切换策略一个典型的低功耗应用可能会这样设计上电后运行在FEE模式进行高速计算和通信空闲时切换到FBE模式CPU降频运行FLL保持预热进入深度休眠时再切换到FBELP模式并关闭FLL当唤醒事件发生时先从FBELP切回FBE等待短暂稳定再切回FEE进行高速处理。4.2 Stop模式下的时钟保持Stop模式是功耗最低的模式之一CPU和大部分外设时钟都停止。但ICS模块允许你选择性地保留一个参考时钟源用于给实时计数器RTC或唤醒定时器提供时钟。保持内部参考时钟设置ICSC1.IREFSTEN 1并且ICSC1.IRCLKEN 1。这样即使进入Stop模式内部约32kHz的时钟仍然运行功耗极低通常1μA可以为RTC提供时基实现定时唤醒。保持外部参考时钟设置ICSC2.EREFSTEN 1并且ICSC2.ERCLKEN 1。这会让外部晶振在Stop模式下继续工作功耗比内部时钟高可能几十到几百微安但精度也高得多适合需要高精度计时休眠的应用。注意手册中特别提到如果在进入Stop2模式时使用了低频振荡器RANGE0并且它在Stop2期间需要保持活动作为RTC时钟源那么必须在写PPDACK寄存器之前重新配置ICSC2寄存器振荡器控制位。这是一个非常容易遗漏的时序要求如果顺序错了可能导致振荡器在Stop模式下无法正常工作。4.3 从Stop模式唤醒的时钟恢复当MCU从Stop模式唤醒时时钟系统不会立刻回到之前的状态。手册明确警告DCO频率会从Stop前的值恢复到复位值FLL需要重新获取锁定。这意味着如果你从Stop模式唤醒后立即执行对时序敏感的操作比如操作ADC、发送串口数据很可能会出错。正确的做法是在唤醒后的初始化代码中检查时钟状态。如果之前运行在FEI或FEE模式在执行关键任务前必须等待FLL重新锁定。可以通过查询相关状态位虽然ICS模块没有直接的锁定标志更通用的做法是插入一个固定的延时延时时间至少为数据手册中规定的FLL锁定时间tAquire。这个时间通常在毫秒量级。void ExitStopMode(void) { // 1. 执行唤醒源处理... // 2. 重新初始化关键外设可能需要先等时钟稳定 // 3. 插入FLL锁定等待时间 // 这是一个简化的软件延时实际应根据芯片总线频率校准 for(uint16_t i 0; i 0xFFFF; i) { __asm(nop); } // 4. 现在可以安全地执行对时钟敏感的操作了 ADC_StartConversion(); // ... }5. 常见问题排查与调试技巧在实际项目中时钟配置问题导致的故障五花八门。这里我总结几个最典型的坑和排查思路。5.1 问题1外部晶振不起振这是最常见的问题。现象可能是程序下载后不运行或者运行极不稳定。检查硬件匹配电容晶振两端到地的电容负载电容是否匹配晶振规格书的要求通常为10-22pF。不匹配会导致频率偏移或不起振。走线XTAL/EXTAL引脚走线是否尽量短且远离高频或噪声源焊接晶振本身、匹配电容是否焊接良好用示波器探头高阻档触碰EXTAL引脚观察是否有正弦波削顶的正弦波注意探头电容会影响振荡。检查软件配置RANGE位是否根据晶振频率正确设置了RANGE低频31-38k高频1-16M一个16MHz的晶振配了RANGE0肯定不会振。HGO位对于低频率如32.768kHz或高负载电容的晶体尝试将HGO从0改为1增加驱动能力。EREFS位是否设置为1使用晶体如果使用外部有源时钟源应设置为0。等待初始化在切换模式前是否轮询了ICSSC.OSCINIT位直到其为15.2 问题2系统时钟频率不对用示波器测量总线时钟或GPIO翻转频率发现与计算值不符。核对计算严格按照公式一步步计算F_bus (F_ref / RDIV_factor) * FLL_multiplier / BDIV_factor。确保F_ref / RDIV_factor的结果在31.25k~39.0625kHz范围内。检查DMX32位如果使用了32.768kHz晶振并且希望获得最高频率DMX32必须设为1。如果使用了其他频率的晶振DMX32必须设为0否则频率会严重偏离。确认模式读取ICSSC.CLKST和ICSSC.IREFST确认系统实际处于你期望的模式FEI, FEE等。检查Trim值如果使用的是内部时钟FEI/FBI模式频率精度依赖于ICSTRM的校准值。芯片复位时会从Flash特定地址加载工厂校准值。如果这个Flash区域被意外擦写或者你在调试模式BDM下复位此时Trim值被设为默认值0x80内部时钟频率可能会偏差很大。解决方案是在用户程序初始化时主动从出厂预留地址例如0xFFAF读取Trim值并写入ICSTRM。5.3 问题3低功耗模式下降功耗达不到预期测量芯片电流发现进入Stop或FBILP模式后电流仍然有几百微安甚至更高。检查时钟门控除了ICS模块其他外设模块如ADC、Timer、SCI等的时钟是否通过对应的SCGCx寄存器被关闭这是降低动态功耗的关键。检查IO口状态未使用的IO口应配置为输出低电平或输入并使能内部上拉/下拉避免浮空输入导致漏电。确认ICS模式在FBILP/FBELP模式下ICSSC.LP位是否确实为1ICSC1.CLKS和ICSC1.IREFS是否正确可以通过读取寄存器确认。检查Stop模式下的时钟如果希望Stop模式下功耗最低确保IREFSTEN和EREFSTEN都已清零这样所有内部和外部参考时钟都会关闭。5.4 问题4模式切换后程序跑飞在运行中动态切换时钟模式例如从FEE切换到FBELP切换后程序发生死机或复位。遵循正确的切换序列不要一次性更改多个可能互斥的配置位。例如从FEE切换到FBELP正确的顺序可能是先配置目标模式所需的分频等参数但先不切换CLKS/IREFS然后等待当前时钟稳定最后再写入CLKS/IREFS触发模式切换。切换后等待CLKST状态位更新。注意Flash访问有些MCU在高速时钟下才能正常访问Flash。如果切换到极低的时钟频率如内部参考时钟的几十kHzFlash的访问时序可能不满足导致取指错误。解决方法是在切换到低频模式前将关键代码拷贝到RAM中执行或者确保Flash控制器支持低频访问查阅芯片手册的Flash章节。同步问题寄存器配置位的生效需要时间尤其是跨时钟域的配置。在切换关键配置如CLKS,IREFS,DRS后一定要插入足够的NOP指令或通过读取状态寄存器CLKST,IREFST,DRST来等待同步完成而不是立即依赖新时钟频率执行后续代码。调试时钟问题最有力的工具就是示波器和逻辑分析仪。测量EXTAL/XTAL引脚可以判断晶振是否工作。测量一个GPIO引脚编写一段简单的翻转代码GPIOx_PTOR 1;可以非常直观地测量出系统总线时钟的实际频率。把这些实测值与理论计算值对比往往能快速定位问题所在。