1. STM32定时器基础与CubeMX入门第一次接触STM32定时器时我被各种TIMx、PWM、互补输出这些术语搞得晕头转向。直到用上STM32CubeMX这个神器才发现原来定时器配置可以这么直观。定时器在嵌入式系统里就像人体的心跳为各种功能提供精准的时间基准。STM32的定时器分为基础定时器(TIM6/TIM7)、通用定时器(TIM2-TIM5)和高级定时器(TIM1/TIM8)每种都有独特的应用场景。打开CubeMX新建工程时我建议先关注时钟树配置。以STM32F103为例默认72MHz主频下定时器的时钟源可能来自APB1或APB2总线。这里有个容易踩坑的地方APB1总线上的定时器时钟频率会被自动倍频2倍所以TIM2-TIM7实际工作频率是72MHz而不是APB1的36MHz。在Clock Configuration界面那些标红的地方就是需要特别注意的时钟冲突点。基础定时器是最简单的只能做基本的定时中断。我常用它来做系统心跳时钟或者延时基准。配置TIM6时主要关注三个参数Prescaler预分频系数决定时钟分频比Counter Mode计数模式向上/向下/中央对齐Period自动重装载值决定定时周期比如要实现500ms定时中断假设系统时钟72MHz可以这样计算 预分频设为7200-1因为从0开始计数自动重装载值设为5000-1。这样定时器频率72MHz/(7200×5000)2Hz周期正好是500ms。在CubeMX里配置好后记得勾选NVIC中断使能否则不会触发中断回调。生成的代码中关键是要在main()里启动定时器HAL_TIM_Base_Start_IT(htim6);然后在stm32f1xx_it.c中实现中断回调void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ if(htim-Instance TIM6){ HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_5); // 翻转LED } }2. 通用定时器PWM实战技巧通用定时器才是真正的多面手我最常用TIM2-TIM5来生成PWM信号控制电机或LED亮度。在电机控制项目中PWM频率选择很关键太高会导致MOS管发热太低电机会有啸叫声。通过CubeMX配置PWM时这几个参数需要特别注意Channel配置选择PWM Generation CHx模式Pulse初始占空比小于Period值Fast Mode需要快速响应时可开启CH Polarity决定PWM初始电平PWM频率计算公式为Fpwm Fclock / (Prescaler 1) / (Period 1)比如要生成50Hz的PWM周期20ms72MHz时钟下可以设Prescaler7200-1Period200-1。这样计算得72000000/7200/20050Hz。实际调试时我习惯先用逻辑分析仪抓取波形。CubeMX配置TIM3的CH1输出PWM到PA6引脚后在代码中需要添加HAL_TIM_PWM_Start(htim3, TIM_CHANNEL_1);动态调整占空比有两种方式// 方法1直接操作寄存器 TIM3-CCR1 100; // 设置占空比脉冲值 // 方法2使用HAL库函数 __HAL_TIM_SET_COMPARE(htim3, TIM_CHANNEL_1, 100);有个实用技巧在CubeMX的Parameter Settings标签页可以实时看到参数修改后的频率计算结果避免手工计算错误。对于电机控制我通常会把PWM频率设在15-20kHz之间这个频段既超出人耳听觉范围又不会造成太大开关损耗。3. 高级定时器互补输出详解当项目需要驱动H桥电路时高级定时器的互补输出功能就派上大用场了。TIM1/TIM8支持带死区的互补PWM这是普通定时器做不到的。记得第一次做电机驱动时因为没设置死区时间导致上下管直通烧了好几个MOS管教训深刻。在CubeMX中配置互补PWM时关键步骤包括在Mode配置中选择PWM Generation CHx和PWM Generation CHxN在Parameter Settings中设置死区时间配置刹车(Break)功能引脚可选但建议启用死区时间的计算有点讲究公式是Tdts 1/(定时器输入时钟频率) 死区时间 (DTG[7:0] 0x7F) × Tdts × 2^DTG[7:5]CubeMX很贴心地提供了自动计算功能。比如输入时钟72MHz要设置1us死区可以直接在Dead Time栏输入1000ns。刹车功能是安全关键当刹车引脚触发时会立即关闭所有PWM输出。配置时需要在Pinout视图分配BKIN引脚在Configuration的Parameter Settings中启用刹车设置刹车极性高电平或低电平触发代码部分除了启动主通道PWM还要启动互补通道HAL_TIM_PWM_Start(htim1, TIM_CHANNEL_1); HAL_TIMEx_PWMN_Start(htim1, TIM_CHANNEL_1);调试互补PWM时一定要用示波器的两个通道同时观察主输出和互补输出。正常应该看到两个反相的PWM波且在电平切换时有微小的死区间隔。我曾遇到过因为PCB布局不合理导致死区时间不足的情况后来通过增加硬件RC延迟才解决。4. 定时器高级应用与调试技巧玩转基础功能后可以尝试一些高级玩法。比如用定时器做输入捕获测量脉冲宽度或者用从模式实现定时器同步。在电机编码器接口项目中我常用TIM2的编码器模式来读取正交编码器信号。CubeMX配置编码器接口时要注意选择Encoder Mode设置IC1和IC2的Polarity根据编码器信号决定调整滤波器参数防抖动定时器同步是另一个实用功能。假设需要TIM2和TIM3同步启动可以配置TIM2为主模式(Master)TIM3为从模式(Slave)。在CubeMX的Trigger Output参数中选择Enable作为TRGO源然后在Slave Mode中选择Trigger Mode。调试复杂定时器配置时我总结了几条经验先用简单的参数测试基本功能正常逐步添加复杂功能每步都验证善用CubeMX的时钟图和引脚冲突检查关键寄存器设置要参考STM32参考手册遇到问题时可以检查这些常见点定时器时钟是否使能__HAL_RCC_TIMx_CLK_ENABLEGPIO是否配置为复用功能中断优先级设置是否合理计数器是否真的启动了CR1寄存器的CEN位对于需要精确时序的应用建议关闭中断和其他后台任务进行测试。我曾经有个项目PWM输出偶尔会有毛刺最后发现是USB中断打断了PWM更新事件。解决方法是调整中断优先级或者使用DMA来传输PWM数据。