尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

STM32定时器深度解析:从基础原理到PWM、捕获三大实战应用

STM32定时器深度解析:从基础原理到PWM、捕获三大实战应用 1. 从“闹钟”到“心脏”为什么STM32定时器是嵌入式开发的基石如果你刚开始接触STM32可能会觉得定时器Timer这个概念有点抽象不就是个“闹钟”吗设置一个时间时间到了就提醒一下。但当你真正深入项目无论是想用PWM驱动一个电机让它平稳转动还是想精确测量一个脉冲的宽度或者只是想让一个LED灯以固定的频率闪烁你都会发现那个看似简单的“闹钟”其实是整个系统协调运行的“心脏”。它远不止于计时更是实现精准控制、信号生成和事件同步的核心硬件单元。我最初做项目时就曾掉进过一个“定时器坑”。当时想用中断做一个非阻塞的延时结果LED闪烁的频率总是不对时快时慢。排查了半天最后发现是定时器的时钟源没有配置正确系统时钟SYSCLK经过分频后给到定时器的实际时钟频率和我计算时假设的完全不一样。这个经历让我深刻体会到不理解定时器就谈不上精通STM32。它不像GPIO点灯那样直观但其重要性在所有复杂外设中绝对排在前列。网络上围绕STM32定时器的搜索热词非常集中stm32定时器捕获测频率、stm32cubemx 定时器配置pwm、stm32 定时器精确定时、定时器从模式……这些恰恰是开发者们在实际工作中最常遇到的需求场景。无论是电机控制、电源管理还是通信同步都离不开对定时器的深度驾驭。本文将从一个资深开发者的视角彻底拆解STM32的定时器体系。我不会仅仅罗列寄存器而是结合这些高频需求带你理解其工作原理、设计逻辑并分享那些数据手册上不会写的配置技巧和避坑指南。无论你是正在学习标准库还是HAL库这篇文章都将为你构建一个清晰且实用的定时器知识框架。2. 庖丁解牛深入理解STM32定时器的家族图谱与核心框图STM32的定时器并非单一外设而是一个功能强大、种类繁多的家族。盲目地直接配置寄存器或使用CubeMX生成代码很容易“用牛刀杀鸡”或“用小刀锯大树”。首先我们必须像认识工具一样了解手头有哪些“刀具”以及它们各自最擅长的“工种”。2.1 定时器家族分类找到你的“那把刀”STM32的定时器主要分为以下几类其复杂度和功能依次增强基本定时器Basic Timers如TIM6, TIM7。这是功能最简单的定时器只具备最基础的定时功能即向上计数产生更新事件溢出中断。它没有外部IO不能用于输入捕获或输出比较。它的核心用途就是提供纯粹的时基例如为DAC数模转换器提供触发信号或者为操作系统提供系统节拍。如果你只需要一个简单的、周期性的中断源基本定时器是最轻量、最节省资源的选择。通用定时器General-purpose Timers如TIM2, TIM3, TIM4, TIM5在部分系列中功能更强。这是STM32定时器家族的“主力军”也是我们最常打交道的类型。它包含了基本定时器的所有功能并大幅扩展双向计数支持向上、向下、中央对齐向上向下计数模式。输入捕获可以捕获外部引脚上信号的边沿并记录下发生时的计数器值用于测量脉冲宽度、频率等。输出比较可以比较计数器值与预设值匹配时产生相应动作如翻转引脚、产生脉冲、产生中断这是生成PWM波的基础。PWM生成通过输出比较模式配合自动重载寄存器可以轻松生成频率和占空比可调的PWM信号。编码器接口部分通用定时器可以直接连接正交编码器自动解析电机的位置和速度信号。高级控制定时器Advanced-control Timers如TIM1, TIM8。这是功能最强大的定时器在通用定时器的基础上增加了用于电机控制和数字电源的“高级货”互补输出可以输出带死区插入的互补PWM对这是驱动三相全桥电路如BLDC电机、逆变器的必备功能能有效防止上下桥臂直通短路。刹车输入紧急情况下通过一个外部引脚信号可以快速关闭所有PWM输出确保系统安全。更灵活的输出模式。选择定时器的原则是用最合适的而不是最强大的。驱动一个LED呼吸灯用通用定时器的PWM功能足矣而为BLDC电机设计FOC算法则必须使用高级控制定时器来生成互补PWM。2.2 核心框图解读数据手册里的“藏宝图”定时器的参考手册里都会有一张复杂的框图很多新手会直接跳过。但在我看来这张图是理解定时器如何工作的“藏宝图”。我们以通用定时器为例拆解几个最关键的部分时钟源这是定时器计数的“心跳”。它可以是内部时钟CK_INT即来自APB总线如APB1、APB2的时钟。这里有一个关键细节当APB预分频器不为1时定时器时钟会是APB时钟的2倍。例如AHB72MHzAPB1预分频器设为2则APB1时钟为36MHz但连接到APB1的定时器如TIM2-4的时钟源会是72MHz。这是很多初学者计算定时不准的第一个坑。其他时钟源还包括外部时钟模式1从TIx引脚输入、外部时钟模式2ETR引脚、内部触发输入ITRx用于定时器级联。时基单元这是定时器的“核心引擎”由预分频器PSC、计数器CNT和自动重载寄存器ARR构成。PSC对时钟源进行分频得到计数器实际递增的时钟频率CK_CNT CK_PSC / (PSC 1)。PSC是一个16位寄存器决定了定时器的分辨率。CNT根据计数模式向上、向下、中央对齐在0到ARR或ARR到0之间循环计数。ARR决定了计数器的周期。当计数器达到这个值向上计数或回到0向下计数时会产生更新事件UEV计数器重置并可以触发更新中断。定时周期T (ARR 1) * (PSC 1) / T_clk。这里的1是因为寄存器值是从0开始计数的。例如要产生1ms的中断系统时钟72MHz可以设PSC7199ARR9。计算T (91)*(71991)/72,000,000 10*7200/72,000,000 0.001s。输入捕获/输出比较通道这是定时器与外部世界交互的“手脚”。输出比较通道寄存器CCRx存放一个比较值。计数器CNT不断与CCRx比较根据设定的模式冻结、匹配时置高、匹配时置低、翻转来操作对应的输出引脚OCx这是产生PWM的硬件基础。输入捕获当对应的输入引脚ICx检测到设定的边沿上升沿、下降沿时会将当前CNT的值锁存到捕获/比较寄存器CCRx中并可以产生中断。通过记录两次捕获的值就能算出脉冲宽度。理解了这个框图你就再也不会觉得配置定时器是一堆魔幻数字了。每一个配置项都能在框图中找到它的位置和作用。3. 实战精讲三大核心应用场景的配置与避坑指南理解了原理我们进入实战。下面我将围绕三个最高频的搜索热词场景详细讲解配置步骤、代码逻辑并分享我踩过的坑。3.1 场景一精确的定时中断——系统的心跳需求不使用HAL_Delay这类阻塞函数而是创建一个1ms的定时器中断用于执行周期性的任务如扫描按键、更新传感器数据。选型使用一个通用定时器如TIM2即可。更简单的系统心跳可以使用SysTick滴答定时器但SysTick通常被HAL库或操作系统占用且功能单一。使用独立定时器更灵活。配置核心以HAL库为例时钟配置确保定时器所在APB总线时钟正确。通过RCC相关函数或CubeMX配置。时基初始化TIM_HandleTypeDef htim2; htim2.Instance TIM2; htim2.Init.Prescaler 7200 - 1; // 72MHz / 7200 10kHz htim2.Init.CounterMode TIM_COUNTERMODE_UP; htim2.Init.Period 10 - 1; // 10kHz / 10 1kHz (1ms) htim2.Init.ClockDivision TIM_CLOCKDIVISION_DIV1; htim2.Init.AutoReloadPreload TIM_AUTORELOAD_PRELOAD_ENABLE; // 建议使能防止更新时出现毛刺 HAL_TIM_Base_Init(htim2);中断配置HAL_TIM_Base_Start_IT(htim2); // 启动定时器并开启更新中断编写中断回调函数void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim-Instance TIM2) { // 你的1ms任务在这里执行 // 例如按键扫描、状态机推进 } }避坑指南与心得坑1中断服务函数ISR过长。1ms中断非常频繁ISR必须短小精悍。只做标记设置标志位把实际处理逻辑放到主循环中。否则会阻塞其他同级或低级中断导致系统响应异常。坑2AutoReloadPreload的作用。这个配置项非常关键。如果不使能DISABLE当你修改ARR值时新值会立即生效。如果此时计数器值刚好在旧ARR和新ARR之间可能会立即触发一次意外的更新事件。如果使能ENABLE则新ARR值会先写入预装载寄存器只在下次更新事件时才生效保证了时序的稳定性。在需要动态改变定时间隔如改变PWM频率时务必使能此功能。心得计算值的验证。配置完PSC和ARR后不要完全相信自己的计算。可以用调试器读取TIMx-CNT寄存器的变化速度或者用PWM输出一个波形用逻辑分析仪测量实际周期进行双重验证。3.2 场景二PWM信号生成——驱动世界的脉搏需求在PA8引脚上生成一个频率为1kHz占空比为30%的PWM波用于控制LED亮度或电机速度。选型查看数据手册找到TIM1的通道1对应PA8。我们使用高级控制定时器TIM1来演示其配置对通用定时器同样具有参考价值。配置核心时基配置决定PWM的频率。Fpwm Fclk / ((PSC1)*(ARR1))。设Fclk72MHz要得到1kHz我们可以令(PSC1)*(ARR1) 72000。为了得到较好的占空比调节分辨率我们让ARR尽量大一些。设PSC0不分频则ARR 72000-1 71999。但ARR是16位寄存器最大值65535此方案不行。重新设计设PSC72-171则Fcnt 72MHz / 72 1MHz。再令ARR 1000-1 999则Fpwm 1MHz / 1000 1kHz。ARR为999占空比分辨率约为0.1%。输出比较配置TIM_OC_InitTypeDef sConfigOC {0}; sConfigOC.OCMode TIM_OCMODE_PWM1; // PWM模式1CNTCCR时有效电平 sConfigOC.Pulse 300; // 占空比CCR值。占空比 Pulse / (ARR1) 300/1000 30% sConfigOC.OCPolarity TIM_OCPOLARITY_HIGH; // 有效电平为高 sConfigOC.OCFastMode TIM_OCFAST_DISABLE; sConfigOC.OCIdleState TIM_OCIDLESTATE_RESET; HAL_TIM_PWM_ConfigChannel(htim1, sConfigOC, TIM_CHANNEL_1);启动PWMHAL_TIM_PWM_Start(htim1, TIM_CHANNEL_1);动态调节占空比// 在程序运行中可以通过修改CCR1寄存器来改变占空比 __HAL_TIM_SET_COMPARE(htim1, TIM_CHANNEL_1, new_pulse_value); // 或者使用HAL库函数 TIM_OC_InitTypeDef sConfigOC; sConfigOC.Pulse new_pulse_value; HAL_TIM_PWM_ConfigChannel(htim1, sConfigOC, TIM_CHANNEL_1); HAL_TIM_PWM_Start(htim1, TIM_CHANNEL_1);避坑指南与心得坑1引脚复用功能未开启。除了配置定时器必须确保GPIO引脚被正确初始化为复用推挽输出模式并映射到对应的定时器通道上。在CubeMX中勾选对应功能会自动完成但手写代码时容易遗漏。GPIO_InitStruct.Pin GPIO_PIN_8; GPIO_InitStruct.Mode GPIO_MODE_AF_PP; // 复用推挽输出 GPIO_InitStruct.Pull GPIO_NOPULL; GPIO_InitStruct.Speed GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate GPIO_AF1_TIM1; // 关键指定复用功能为TIM1 HAL_GPIO_Init(GPIOA, GPIO_InitStruct);坑2高级控制定时器的“主输出使能”。对于TIM1/TIM8配置好PWM后还需要使能“刹车和死区寄存器BDTR”中的主输出使能MOE位否则PWM输出会被禁止。这在驱动互补输出时是必须的但在普通单通道输出时也建议开启。__HAL_TIM_MOE_ENABLE(htim1); // 或使用HAL库函数 HAL_TIMEx_PWMN_Start(htim1, TIM_CHANNEL_1); // 对于互补通道 // 对于普通通道在HAL_TIM_PWM_Start内部可能会处理但最好显式调用以下函数确保 HAL_TIMEx_MasterConfigSynchronization(htim1, sMasterConfig);心得PWM频率与分辨率权衡。PWM频率越高电机或LED的响应越快噪音可能越小对于电机驱动频率需高于人耳可闻范围通常20kHz。但频率越高在系统时钟固定的情况下ARR值就越小导致占空比调节的分辨率越低。例如72MHz时钟要产生20kHz的PWMARR最大只能为72M/20k -1 3599分辨率只有1/3600。你需要根据实际应用在频率和分辨率之间做出取舍。3.3 场景三输入捕获测量频率与脉宽——感知信号的脉搏需求测量输入到某个引脚上的方波信号的频率或高电平脉宽。选型使用通用定时器的输入捕获功能。例如用TIM3的通道1可能对应PA6。配置核心以测量脉宽为例 测量脉宽通常需要捕获上升沿和下降沿。有两种常用方法方法A单通道两次捕获。将通道配置为在上升沿和下降沿都触发捕获。在上升沿中断中记录捕获值并改变极性为下降沿在下降沿中断中再次记录捕获值差值即为脉宽。此法节省定时器资源但软件逻辑稍复杂且高频率下可能丢失中断。方法B双通道联合捕获推荐。使用同一个定时器的两个通道如CH1和CH2分别设置为上升沿触发和下降沿触发并配置为从模式复位模式将CH1设为触发源。这样上升沿时计数器清零并开始计数下降沿时捕获当前计数值该值即为高电平脉宽。此法硬件自动完成精度高不占用过多CPU。配置步骤方法BHAL库时基配置根据信号频率范围设置合适的PSC使计数器在最大脉宽内不会溢出。例如测1ms内脉宽时钟1MHz则ARR需大于1000。输入捕获通道1上升沿TIM_IC_InitTypeDef sConfigIC; sConfigIC.ICPolarity TIM_ICPOLARITY_RISING; // 上升沿 sConfigIC.ICSelection TIM_ICSELECTION_DIRECTTI; // 直接映射到TI1 sConfigIC.ICPrescaler TIM_ICPSC_DIV1; // 不分频每个边沿都捕获 sConfigIC.ICFilter 0; // 滤波器值根据信号噪声情况设置 HAL_TIM_IC_ConfigChannel(htim3, sConfigIC, TIM_CHANNEL_1);输入捕获通道2下降沿sConfigIC.ICPolarity TIM_ICPOLARITY_FALLING; // 下降沿 sConfigIC.ICSelection TIM_ICSELECTION_INDIRECTTI; // 间接映射从TI1输入 HAL_TIM_IC_ConfigChannel(htim3, sConfigIC, TIM_CHANNEL_2);从模式配置TIM_SlaveConfigTypeDef sSlaveConfig; sSlaveConfig.SlaveMode TIM_SLAVEMODE_RESET; // 复位模式 sSlaveConfig.InputTrigger TIM_TS_TI1FP1; // 触发源为TI1的滤波后信号 sSlaveConfig.TriggerPolarity TIM_TRIGGERPOLARITY_RISING; // 上升沿触发复位 sSlaveConfig.TriggerFilter 0; HAL_TIM_SlaveConfigSynchro(htim3, sSlaveConfig);启动捕获HAL_TIM_IC_Start(htim3, TIM_CHANNEL_1); // 启动通道1捕获用于触发复位 HAL_TIM_IC_Start_IT(htim3, TIM_CHANNEL_2); // 启动通道2捕获并开中断中断回调函数中读取脉宽void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if (htim-Instance TIM3 htim-Channel HAL_TIM_ACTIVE_CHANNEL_2) { uint32_t pulse_width HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2); // pulse_width 即为高电平期间的计数值根据时钟频率可换算为时间 // 注意如果脉宽可能超过ARR需要处理溢出或使用捕获溢出中断进行计数扩展。 } }避坑指南与心得坑1信号抖动与滤波器。如果被测信号有毛刺会导致误触发。定时器的输入捕获单元内置了数字滤波器通过ICFilter参数配置。它的原理是连续采样N次只有连续N次电平一致才认为有效边沿。N值越大抗干扰能力越强但会引入微小延迟。需要根据信号质量和系统要求折中设置。坑2脉宽超过ARR溢出。如果高电平时间太长计数器从0开始计数在到达下降沿之前就已经溢出归零那么捕获到的值就不是真实的脉宽了。解决方法有两种一是降低定时器时钟频率增大PSC让计数器计得更慢二是开启定时器的更新中断在中断里对一个全局变量进行累加记录溢出次数。最终脉宽 溢出次数 * (ARR1) 本次捕获值。心得测量频率的简便方法。除了用脉宽换算更常用的测频方法是输入捕获从模式触发。配置一个通道为上升沿捕获并设置为从模式复位模式触发源为自己。这样每个上升沿计数器复位。同时使能另一个定时器的更新中断固定时间如1秒后读取该通道的捕获值即两次上升沿间的计数值这个值就是1秒内的脉冲个数直接得到频率。这种方法硬件自动完成计数软件只需在固定时间点读取非常高效准确。4. 进阶与排错应对复杂需求与诡异问题掌握了基础应用我们来看看更复杂的场景和那些让人头疼的调试问题。4.1 定时器的级联与同步构建复杂时序系统当单个定时器不够用或者需要创建非常长的定时周期、需要精确同步多个定时事件时就需要用到定时器的级联或称主从模式。典型应用用一个定时器TIM2的更新事件去触发另一个定时器TIM3的启动。这样TIM3的计数周期就是TIM2周期的整数倍可以实现超长定时。或者用TIM1作为主定时器产生PWM用TIM2作为从定时器由TIM1的更新事件触发其开始ADC采样实现PWM中心点与ADC采样的严格同步在电机FOC控制中至关重要。配置逻辑配置主定时器Master正常配置其时基和更新事件。在TIMx-CR2寄存器中设置MMS主模式选择为010更新事件作为触发输出。配置从定时器Slave正常配置其时基。在从定时器的TIMx-SMCR寄存器中设置TS触发选择为对应的ITRx内部触发。例如TIM2作为TIM3的从机则TIM3的TS应选择ITR1具体对应关系需查数据手册。设置SMS从模式选择为触发模式或门控模式等。例如设为触发模式则主定时器的更新事件一来从定时器就开始计数。避坑点级联时时钟源必须同步。通常所有定时器使用相同的APB总线时钟。确保主定时器先启动从定时器处于等待触发状态。4.2 那些年我踩过的“定时器坑”与排查思路即使理解了原理调试时依然会遇到各种诡异现象。下面分享几个典型案例问题一定时器中断一次都不进。排查链时钟树首先确认该定时器的外设时钟是否使能__HAL_RCC_TIMx_CLK_ENABLE()调用了吗NVIC配置中断向量表里配置了该定时器的中断服务函数吗NVIC的优先级和使能位设置了吗在CubeMX生成的代码中有时会漏掉HAL_NVIC_EnableIRQ(TIMx_IRQn)这一行。中断标志在调试器中查看定时器的SR寄存器更新中断标志UIF是否置位如果置位了但没进中断问题大概率在NVIC如果没置位问题在定时器本身配置。计数器状态CNT寄存器在动吗如果不动检查CEN位是否置1定时器是否启动再回溯检查时钟源配置。问题二PWM没有输出或者输出固定电平。排查链GPIO复用这是最高频的错误。确认引脚模式是AF_PP复用推挽输出吗Alternate功能号选对了吗用示波器或万用表测一下引脚如果是高阻态肯定是GPIO配置问题。高级定时器的MOE位如果是TIM1/TIM8检查BDTR寄存器的MOE位是否为1。输出比较模式确认CCMR寄存器中通道的模式是PWM模式1或2吗CCR值CCR寄存器的值是否在0和ARR之间如果为0输出可能一直是无效电平。引脚冲突该引脚是否被其他外设如串口、SPI占用了问题三输入捕获值跳动很大不准。排查链信号质量首先用示波器看被测信号是否干净是否有振铃或毛刺这是硬件问题。滤波器设置如果信号有噪声尝试增大ICFilter值。边沿检测确认设置的捕获极性上升/下降沿与实际信号是否一致中断处理延迟如果使用单通道两次捕获的中断方式在高频下CPU可能来不及处理中断导致丢失边沿。考虑使用双通道硬件捕获法或者降低信号频率。计数器溢出测量长脉宽时是否处理了计数器溢出如前所述需要结合更新中断来扩展计数范围。一个实用的调试技巧当你怀疑定时器配置有问题时可以暂时将其配置为PWM输出模式并设置一个固定的占空比。用示波器测量输出波形。如果波形频率、占空比符合预期证明时基单元和输出比较单元的配置是正确的问题可能出在中断、DMA或特定模式如输入捕获的配置上。这是一种“功能验证法”能快速定位问题模块。5. 超越数据手册项目实战中的经验沉淀最后分享一些在真实项目中积累的、超越官方文档的实用经验。5.1 动态重载PSC与ARR实现“无感”的频率切换在电机控制、音频生成等场景需要动态改变PWM频率。粗暴地直接修改ARR或PSC寄存器可能导致当前周期被截断产生非对称的畸形波形。优雅的做法利用预装载寄存器和更新事件。确保TIMx-CR1寄存器中的ARPE位使能Auto-reload preload enable。在需要修改频率时计算新的PSC和ARR值写入TIMx-PSC和TIMx-ARR寄存器。此时新值只是写入了预装载寄存器并未生效。通过软件设置TIMx-EGR寄存器的UG位Update generation或等待下一次硬件更新事件到来。在更新事件发生时预装载寄存器的值才会被传递到影子寄存器从而真正生效。这样可以保证频率切换发生在完整的PWM周期边界波形连续平滑。在HAL库中可以使用__HAL_TIM_SET_AUTORELOAD()和__HAL_TIM_SET_PRESCALER()来设置值然后调用__HAL_TIM_GENERATE_EVENT(htim, TIM_EVENTSOURCE_UPDATE)来生成更新事件。5.2 定时器与DMA的联姻解放CPU的高效数据搬运定时器触发DMA是STM32外设联动的经典应用能极大减轻CPU负担。常见场景有DAC输出波形定时器更新事件触发DMA将波形数据表如正弦波数组逐个搬运到DAC数据寄存器实现高速、精确的模拟信号合成。ADC规则扫描定时器触发ADC开始一组通道的扫描转换转换完成后由DMA将结果搬运到内存数组。这是实现固定采样率数据采集的黄金组合。PWM控制序列通过DMA动态更新多个通道的CCR值可以实现复杂、预定义的PWM波形序列。配置关键点配置DMA流或通道设置外设地址为定时器的CCR寄存器地址对于PWM或ARR寄存器地址对于改变频率内存地址为你的数据数组。在DMA配置中选择触发源为对应的定时器事件如TIMx_UP更新事件TIMx_CH1比较事件等。使能定时器的相应DMA请求如TIMx-DIER寄存器中的CCxDE或UDE位。启动DMA然后启动定时器。定时器事件会像节拍器一样自动驱动DMA进行数据搬运。5.3 低功耗模式下的定时器生存之道在电池供电设备中MCU常需进入低功耗模式如Stop模式。但很多定时器在Stop模式下会停止工作因为其时钟源HSI/HSE被关闭了。解决方案使用低功耗定时器LPTIM。LPTIM是STM32中专门为低功耗场景设计的定时器它可以在多种低功耗模式下运行时钟源可以是LSI内部低速、LSE外部低速甚至系统时钟。虽然功能比通用定时器简单通常只支持单次或连续计数、比较、PWM输出但用于唤醒、基本计时绰绰有余。设计思路在进入深度睡眠前配置LPTIM在指定时间后产生中断或唤醒事件。然后MCU进入Stop模式。LPTIM依靠LSI/LSE继续计数时间一到即唤醒MCU。这样既实现了定时功能又保证了极低的功耗。从基本定时到PWM生成从信号捕获到复杂联动STM32的定时器外设展现了一个由简入繁、深度集成的硬件世界。理解它不仅仅是记住几个API函数更是要读懂数据手册中的框图理解每个寄存器位背后的硬件逻辑。我个人的体会是定时器是区分“单片机程序员”和“嵌入式系统工程师”的一道坎。跨过去你就能设计出时序精准、响应及时、资源高效的系统。下次当你面对电机不转、采样不准、通信不同步的问题时不妨先从定时器的配置和时钟树查起或许就能找到那把关键的钥匙。
返回列表