用STM32的TIM3输入捕获测PWM频率和占空比,一个OLED屏就能搞定(附完整代码)
STM32实战用TIM3输入捕获精准测量PWM信号并实时显示去年调试无人机电调时我遇到一个棘手问题需要实时监测电机控制信号的频率和占空比但手头只有一块STM32开发板和0.96寸OLED屏。经过反复实验最终用TIM3的输入捕获功能实现了这个需求测量误差小于0.1%。下面分享这个既实用又有趣的方案。1. 硬件搭建与核心原理1.1 所需材料清单STM32F103C8T6最小系统板蓝色药丸0.96寸OLED显示屏I2C接口PWM信号源可用另一个STM32生成杜邦线若干USB转TTL模块可选用于调试关键点OLED屏建议选择SSD1306驱动的型号其兼容性好且库函数丰富。PWM输入引脚使用PA6TIM3_CH1这是STM32F103的默认映射。1.2 输入捕获工作原理TIM3的输入捕获单元本质上是一个智能秒表当检测到指定边沿上升/下降沿时立即记录当前CNT值到CCR寄存器通过两次捕获的差值计算信号时间参数PWMI模式可同时捕获两个边沿实现占空比测量技术细节STM32的输入捕获具有8级可编程数字滤波器能有效消除信号抖动。例如设置滤波器值为0x7时需要8个连续相同采样才会确认边沿变化。测量原理公式频率 定时器时钟 / (PSC1) / CCR1 占空比 CCR2 / CCR1 * 100%2. 软件配置关键步骤2.1 定时器初始化代码void TIM3_IC_Init(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct; TIM_ICInitTypeDef TIM_ICInitStruct; // 时钟使能 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); // 时基配置 TIM_TimeBaseStruct.TIM_Prescaler 72-1; // 1MHz计数频率 TIM_TimeBaseStruct.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseStruct.TIM_Period 0xFFFF; TIM_TimeBaseStruct.TIM_ClockDivision TIM_CKD_DIV1; TIM_TimeBaseInit(TIM3, TIM_TimeBaseStruct); // 输入捕获配置(PWMI模式) TIM_ICInitStruct.TIM_Channel TIM_Channel_1; TIM_ICInitStruct.TIM_ICPolarity TIM_ICPolarity_Rising; TIM_ICInitStruct.TIM_ICSelection TIM_ICSelection_DirectTI; TIM_ICInitStruct.TIM_ICPrescaler TIM_ICPSC_DIV1; TIM_ICInitStruct.TIM_ICFilter 0x07; TIM_PWMIConfig(TIM3, TIM_ICInitStruct); // 自动配置互补通道 // 触发设置 TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1); TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset); TIM_Cmd(TIM3, ENABLE); }2.2 测量函数实现float Get_PWM_Freq(void) { return 1000000.0f / (TIM_GetCapture1(TIM3) 1); } uint8_t Get_PWM_Duty(void) { return (TIM_GetCapture2(TIM3)1) * 100 / (TIM_GetCapture1(TIM3)1); }3. OLED显示优化技巧3.1 防闪烁显示方案直接刷新整个屏幕会导致明显闪烁推荐采用差异更新策略void OLED_UpdateDisplay(float freq, uint8_t duty) { static float last_freq 0; static uint8_t last_duty 0; if(fabs(freq - last_freq) 1.0){ OLED_ShowNum(2, 6, (uint32_t)freq, 5); last_freq freq; } if(duty ! last_duty){ OLED_ShowNum(3, 6, duty, 2); last_duty duty; } }3.2 界面布局建议行号内容示例显示1项目标题PWM测量仪2频率值Freq: 1000Hz3占空比Duty: 50%4状态提示Stable4. 实战调试经验4.1 常见问题排查表现象可能原因解决方案测量值恒为0引脚配置错误检查GPIO是否设置为上拉输入频率值明显偏小滤波器设置过大减小TIM_ICFilter参数占空比显示跳变信号噪声大增加硬件RC滤波或软件滤波OLED无显示I2C地址不匹配尝试0x3C或0x3D地址4.2 精度提升技巧将定时器时钟源改为外部晶振误差可降至0.01%多次测量取平均值动态调整预分频器高频时减小PSC低频时增大PSC使用DMA传输捕获数据减少CPU干预void Auto_Adjust_Prescaler(float freq) { if(freq 50000) TIM3-PSC 0; // 72MHz else if(freq 5000) TIM3-PSC 9; // 7.2MHz else TIM3-PSC 72; // 1MHz }这个项目最让我惊喜的是STM32输入捕获单元的稳定性——即使在电机干扰环境下通过合理配置滤波器依然能获得可靠的测量结果。实际应用中建议在PA6引脚添加100Ω电阻和100pF电容组成简单滤波电路这对抑制高频噪声特别有效。