频率测量在电子工程领域是个基础但极其重要的功能。无论是调试振荡电路、校准信号发生器,还是分析传感器输出,我们都需要准确知道信号的频率值。传统台式频率计虽然精度高,但体积大、价格昂贵,很多场合我们需要更灵活的解决方案。
这个项目就是要用STM32打造一个便携式数字频率计。相比专用IC方案(如等精度频率计芯片),STM32方案有三个明显优势:首先是成本,一片STM32F103C8T6核心板不到20元;其次是灵活性,我们可以通过编程实现自动量程切换、占空比测量等扩展功能;最重要的是可集成性,它能直接嵌入到其他系统中作为子模块。
我选择STM32F103C8T6作为主控,这款Cortex-M3内核的MCU有以下几个优势:
关键外设分配:
实际测量中会遇到各种信号,必须设计可靠的前端电路:
circuit复制[信号输入] -> [1MΩ电阻] -> [双向TVS管]
-> [电压跟随器] -> [迟滞比较器]
-> [74HC14整形] -> [MCU输入]
这个电路实现了:
特别注意:比较器参考电压建议设置为0.1Vcc和0.9Vcc,这样可以有效抑制噪声干扰。
采用AMS1117-3.3稳压芯片,注意:
采用测周法与测频法结合的混合测量方案:
代码结构示例:
c复制void TIM2_IRQHandler() {
if(TIM_GetITStatus(TIM2, TIM_IT_CC1)) {
period = TIM_GetCapture1(TIM2);
TIM_SetCounter(TIM2, 0);
}
}
通过动态调整预分频器实现量程切换:
使用0.96寸OLED显示:
时基校准:
软件滤波算法:
c复制#define FILTER_LEN 5
uint32_t moving_avg(uint32_t new_val) {
static uint32_t buf[FILTER_LEN];
static uint8_t idx = 0;
buf[idx++] = new_val;
if(idx >= FILTER_LEN) idx = 0;
uint32_t sum = 0;
for(uint8_t i=0; i<FILTER_LEN; i++) {
sum += buf[i];
}
return sum/FILTER_LEN;
}
PCB布局要点:
软件容错机制:
| 输入信号 | 标称值 | 测量值 | 误差 |
|---|---|---|---|
| 1kHz方波 | 1000Hz | 999.8Hz | 0.02% |
| 10MHz正弦波 | 10MHz | 9.9987MHz | 0.013% |
| 50Hz工频 | 50Hz | 50.1Hz | 0.2% |
高频测量不稳定:
显示值跳变严重:
低幅值信号无法触发:
利用输入捕获的双边沿触发:
c复制TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
添加HC-05蓝牙模块:
code复制[HEAD][LEN][DATA][CRC]
0xAA 1 freq XOR
通过手机APP可以实时查看频率曲线,这个功能在调试振动传感器时特别实用。
改用STM32H743提升性能:
增加FFT频谱分析功能:
外壳与便携设计:
这个项目最让我惊喜的是STM32定时器模块的灵活性,通过合理配置,一片10元级的MCU就能实现专业仪器的核心功能。在实际调试中发现,信号调理电路的质量对测量结果影响巨大,一个好的硬件设计可以大幅降低软件处理复杂度。