STM32G474定时器实战:从PWM调光到编码器测速的进阶应用

张开发
2026/5/18 5:11:47 15 分钟阅读
STM32G474定时器实战:从PWM调光到编码器测速的进阶应用
1. STM32G474定时器基础与PWM调光实战STM32G474的定时器系统堪称单片机外设中的瑞士军刀我在多个电机控制项目中都深度依赖它的PWM生成能力。与基础定时器不同通用定时器TIM2-TIM5、TIM15-TIM17兼具输入捕获和输出比较功能特别适合需要精确时序控制的场景。举个例子当我们需要驱动LED实现呼吸灯效果时PWM调光就是最典型的应用。配置PWM输出其实就三步走首先通过TIMx_PSC设置预分频值将系统时钟降到合适频率然后在TIMx_ARR中设定自动重装载值决定PWM周期最后配置TIMx_CCRx确定占空比。以170MHz主频为例要实现1kHz PWM频率htim3.Instance TIM3; htim3.Init.Prescaler 169; // 分频后1MHz htim3.Init.CounterMode TIM_COUNTERMODE_UP; htim3.Init.Period 999; // 1000个计数周期1kHz HAL_TIM_PWM_Init(htim3); TIM_OC_InitTypeDef sConfigOC; sConfigOC.OCMode TIM_OCMODE_PWM1; sConfigOC.Pulse 300; // 初始占空比30% HAL_TIM_PWM_ConfigChannel(htim3, sConfigOC, TIM_CHANNEL_1);实际调试时我发现如果直接修改CCR值调整亮度偶尔会出现波形毛刺。这是因为ARR和CCR寄存器都有对应的影子寄存器当ARPE1时新参数要等更新事件(UEV)才会生效。通过CubeMX勾选Auto-reload preload选项或者代码中设置TIMx_CR1寄存器的ARPE位就能确保PWM参数同步更新。提示调试PWM时建议先用逻辑分析仪抓波形确认周期和占空比是否符合预期再连接实际负载2. 编码器接口模式实现电机测速去年做AGV小车项目时我通过TIM4的编码器接口成功实现了对直流电机转速的精确测量。STM32G474的编码器模式支持正交解码能自动处理A/B相脉冲相比普通输入捕获方式更加高效。硬件连接上将编码器的A相接TIMx_CH1B相接TIMx_CH2然后在CubeMX中配置选择Encoder Mode作为定时器工作模式设置IC1和IC2为Input Capture direct mode根据编码器类型选择TI1/TI2边沿计数方式初始化完成后定时器计数器会自动根据编码器旋转方向增减。读取转速的典型代码逻辑如下int32_t GetEncoderSpeed(TIM_HandleTypeDef *htim) { static int32_t last_count 0; int32_t current_count (int32_t)__HAL_TIM_GET_COUNTER(htim); int32_t diff current_count - last_count; last_count current_count; // 假设编码器1000线采样周期10ms return diff * 100 / (1000 * 4); // 转/分钟 }实测中发现两个常见问题一是高速旋转时可能溢出需要开启定时器溢出中断二是机械振动会导致误脉冲可以通过配置输入滤波解决。在TIMx_CCMR1寄存器中设置IC1F和IC2F滤波参数能有效消除噪声干扰。3. 输入捕获测量脉冲宽度除了编码器模式用普通输入捕获功能也能实现频率测量。我曾用这个方法成功检测过红外遥控信号的38kHz载波。以TIM2_CH1测量方波频率为例关键配置包括通道配置为输入捕获模式设置边沿检测极性上升沿/下降沿开启捕获中断必要时配置预分频器降低计数频率测量原理是记录连续两个上升沿之间的计数器差值。假设系统时钟为100MHz预分频设为99则每个计数周期为1μs。如果测得N个计数则周期为N微秒频率为1000000/N Hz。核心中断处理代码void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if(htim-Instance TIM2) { static uint32_t last_capture 0; uint32_t current_capture HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); if(last_capture ! 0) { uint32_t period (current_capture last_capture) ? (current_capture - last_capture) : (0xFFFF - last_capture current_capture); g_frequency 1000000.0f / period; // 单位Hz } last_capture current_capture; } }对于低频信号1kHz这种方法精度很高。但测量高频信号时建议使用定时器的PWM输入模式它能自动捕获一个完整周期的高低电平时间。4. 高级应用定时器级联与同步在需要多通道精确同步的场景比如三相电机控制定时器的级联功能就派上用场了。STM32G474允许将一个定时器作为主设备其他定时器作为从设备通过内部触发线实现同步。我最近做的一个LED矩阵控制项目就用到这个特性TIM1作为主定时器产生100Hz基准时钟TIM2和TIM3作为从定时器分别控制不同区域的LED亮度。配置步骤如下主定时器TIM1配置为PWM模式使能主从模式TIM1-CR2 | TIM_CR2_MMS_1; // 更新事件作为触发输出从定时器TIM2/TIM3配置为从模式TIM2-SMCR | TIM_SMCR_SMS_2 | // 触发模式 TIM_SMCR_TS_2; // 选择ITR1触发源启动所有定时器时先启动从定时器再启动主定时器这种架构下修改TIM1的ARR值会同步影响所有定时器确保各通道PWM相位一致。实测同步误差小于50ns完全满足严苛的时序要求。

更多文章