用STM32的TIM3输入捕获功能,5分钟搞定PWM信号频率和占空比的测量
5分钟实战STM32 TIM3输入捕获精准测量PWM频率与占空比第一次接触STM32的输入捕获功能时我盯着数据手册里那些寄存器描述发呆了半小时——直到在面包板上连好线看到OLED上跳动的数字那一刻才恍然大悟。本文将带你跳过理论深坑用最简配置实现PWM测量就像用万用表测电压一样直观。1. 硬件准备与连接找一块STM32F103C8T6核心板蓝色小板、一块OLED显示屏和几根杜邦线就够了。信号源可以用另一块STM32的PWM输出PA0引脚函数信号发生器555定时器电路关键连接点PWM信号源 → PA6TIM3通道1OLED的I2C接口 → PB6(SCL), PB7(SDA)注意如果使用3.3V电平的信号源建议在输入引脚加1kΩ上拉电阻避免信号抖动。2. 极简工程配置打开STM32CubeIDE新建工程时只需勾选TIM3Channel1输入捕获模式I2C1OLED显示USART1可选用于调试输出// 时钟树配置保持默认即可 // HCLK 72MHz // APB1 Timer clocks 72MHz3. 核心代码实现3.1 输入捕获初始化void TIM3_IC_Init(void) { TIM_HandleTypeDef htim3; htim3.Instance TIM3; htim3.Init.Prescaler 71; // 72MHz/(711)1MHz计数频率 htim3.Init.CounterMode TIM_COUNTERMODE_UP; htim3.Init.Period 0xFFFF; // 最大计数值 HAL_TIM_IC_Init(htim3); TIM_IC_InitTypeDef sConfigIC; sConfigIC.ICPolarity TIM_INPUTCHANNELPOLARITY_RISING; sConfigIC.ICSelection TIM_ICSELECTION_DIRECTTI; sConfigIC.ICPrescaler TIM_ICPSC_DIV1; sConfigIC.ICFilter 0; HAL_TIM_IC_ConfigChannel(htim3, sConfigIC, TIM_CHANNEL_1); // 开启PWM模式自动捕获 HAL_TIM_PWM_Init(htim3); HAL_TIM_IC_Start(htim3, TIM_CHANNEL_1); HAL_TIM_IC_Start(htim3, TIM_CHANNEL_2); // 自动映射到下降沿捕获 }3.2 测量计算函数float Get_PWM_Freq(void) { uint32_t ic1 HAL_TIM_ReadCapturedValue(htim3, TIM_CHANNEL_1); return 1000000.0f / ic1; // 单位Hz } float Get_PWM_Duty(void) { uint32_t ic1 HAL_TIM_ReadCapturedValue(htim3, TIM_CHANNEL_1); uint32_t ic2 HAL_TIM_ReadCapturedValue(htim3, TIM_CHANNEL_2); return (ic2 * 100.0f) / ic1; // 百分比 }4. 实测效果优化技巧在实验室测试1kHz PWM信号时发现三个常见问题及解决方案问题现象可能原因解决方法测量值跳变大信号抖动增加TIM_ICFilter值0-15高频测量不准计数器溢出降低Prescaler值占空比误差大边沿检测延迟改用定时器互补通道示波器对比数据输入信号1kHz50%占空比测量结果无滤波998Hz±5Hz49%-51%滤波值61001Hz±1Hz50.2%-50.8%5. 进阶应用方向掌握基础测量后可以尝试动态范围扩展通过自动切换预分频器实现1Hz-1MHz宽范围测量if(TIM3-CCR1 60000) { TIM3-PSC 719; // 100kHz量程 } else { TIM3-PSC 71; // 1MHz量程 }多通道同步测量利用TIM3的其余通道同时监测多路PWM异常检测通过中断捕获丢失脉冲或占空比突变记得第一次成功测出无人机电调信号时那组200Hz的PWM波形让我突然理解了无刷电机控制的精髓——有时候最有效的学习就是先看到数据跳动再回头理解理论。