手里有块吃灰的STM32开发板?别急着买示波器!今天我要分享一个创客圈里鲜为人知的技巧——用最常见的STM32最小系统板制作精准频率计。这个方案特别适合调试PWM信号,成本不到专业设备的1%,却能解决80%的日常测量需求。
核心思路:让同一块开发板同时担任信号发生器和频率计。TIM3负责生成PWM测试信号,TIM2则通过外部触发模式(ETR)捕获输入频率。这种设计最妙的地方在于:
注意:STM32F103系列定时器时钟树结构特殊,TIM1/8在APB2总线(最高72MHz),TIM2-7在APB1总线(最高36MHz)
定时器配置关键参数对比:
| 定时器 | 功能 | 时钟源 | 典型配置 | 精度影响因子 |
|---|---|---|---|---|
| TIM1 | 时基 | APB2 | 1秒中断 | 晶振稳定性 |
| TIM2 | 脉冲计数 | ETR外部触发 | 最大计数周期(0xFFFF) | 信号边沿质量 |
| TIM3 | PWM生成 | 内部时钟 | 72分频(1MHz) | 占空比分辨率 |
c复制// TIM2初始化代码片段 - 外部脉冲计数模式
TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF,
TIM_ExtTRGPolarity_NonInverted, 0);
TIM_SetCounter(TIM2, 0);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
测量逻辑的核心在于两个定时器的协同工作:TIM1产生固定时间基准(如1秒),TIM2在该时间段内统计脉冲上升沿次数。但实际开发中会遇到几个关键问题:
常见痛点及解决方案:
高频信号漏计数:当输入频率超过TIM2时钟1/4时,可能丢失边沿
低频信号精度差:测量1Hz以下信号时误差显著
信号抖动干扰:杂波导致误触发
c复制// 改进的中断服务程序 - 加入溢出处理
void TIM1_UP_IRQHandler(void) {
if (TIM_GetITStatus(TIM1, TIM_IT_Update)) {
uint16_t cnt = TIM_GetCounter(TIM2);
total_freq = overflow_cnt * 65535 + cnt;
printf("Freq: %.3f kHz\r\n", total_freq/1000.0);
TIM_SetCounter(TIM2, 0);
overflow_cnt = 0;
}
}
精度提升技巧:
假设我们要调试电机驱动器的PWM信号,典型操作流程如下:
初始化配置
c复制// 产生1kHz PWM,占空比30%
TIM3_PWM_Init(720-1, 0); // 72MHz/720 = 100kHz
TIM_SetCompare1(TIM3, 216); // 720*0.3=216
测量阶段
参数调整
扩展应用
基础版本满足简单测量后,可以考虑以下升级方向:
硬件增强:
软件升级:
python复制# PC端数据处理示例(Python)
import serial
import matplotlib.pyplot as plt
ser = serial.Serial('COM3', 115200)
freq_data = []
for _ in range(100):
line = ser.readline().decode().strip()
freq = float(line.split(':')[-1][:-4])
freq_data.append(freq)
plt.plot(freq_data)
plt.title('Frequency Stability Test')
plt.show()
显示方案对比:
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 串口输出 | 无需额外硬件 | 依赖PC | 实验室调试 |
| OLED | 便携独立使用 | 增加接线复杂度 | 现场测量 |
| LCD触摸屏 | 交互友好 | 占用较多IO资源 | 产品原型 |
| 无线传输 | 远程监控 | 引入延迟 | 物联网应用 |
在帮学员调试项目的过程中,我总结了这些高频问题:
测量结果总是差2倍
检查信号边沿触发方式,PWM通常需要上升沿+下降沿都计数
高频时读数不稳定
尝试降低TIM2的输入滤波器带宽:
c复制TIM_ETRConfig(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0F);
开发板发热严重
可能是时钟配置错误导致超频,检查:
无法触发计数
按这个顺序排查: