3、信号采集硬件接口:MCU的TIM与ADC模块、输入捕获与比较器、外部中断配置
好,咱们接着往下聊。上一章我们把传感器和调理电路搞定了,信号已经变成了干净的方波。但方波进了MCU,怎么把它变成我们能用的轮速数据?这就得靠MCU内部的“硬件接口”了。
说白了,MCU不是直接“读”电压的,它得通过特定的外设模块来感知信号的变化。我个人习惯把这一层叫做“信号采集的最后一公里”。这公里走不好,前面调理得再漂亮也是白搭。
3.1 输入捕获:最常用的轮速采集方式
输入捕获,这名字听着挺唬人。其实原理很简单:它就是用TIM(定时器)来记录信号跳变的时间点。
你想想看,轮速传感器出来的方波,每个上升沿代表齿圈转过了一个齿。如果我们能精确记录每个上升沿到来的时刻,那相邻两个沿的时间差,不就是这个齿的周期吗?
在STM32这类MCU里,配置输入捕获通常就几步:
// 伪代码示意,以STM32 TIM2 CH1为例
TIM_IC_InitTypeDef TIM_ICInitStructure;
// 1. 选择捕获通道和极性(上升沿捕获)
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);
// 2. 使能捕获中断
TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);
// 3. 在中断服务函数里读取捕获值
void TIM2_IRQHandler(void) {
if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET) {
uint32_t capture_value = TIM_GetCapture1(TIM2);
// 这里就拿到了当前上升沿的TIM计数值
TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
}
}
嗯,这里要注意一个细节:捕获值的单位是TIM的时钟节拍。比如TIM时钟是80MHz,那一个节拍就是12.5ns。两个上升沿之间差了10000个节拍,那周期就是125μs。换算成转速,就是60 / (125μs * 齿数) rpm。
3.2 外部中断:简单粗暴的备选方案
有些老工程师或者资源紧张的项目,会用外部中断(EXTI)来采集轮速。原理和输入捕获类似,也是检测跳变沿。
但说实话,我个人不太推荐用外部中断做轮速采集。为什么?
- 精度受限: 外部中断只能告诉你“信号变了”,但没法告诉你“信号是在哪个精确时刻变的”。你得在中断里手动去读一个通用定时器的值,这中间就有延迟和误差。
- 中断开销大: 每个上升沿都进一次中断,如果转速高(比如200km/h,齿圈48齿),中断频率能到几kHz。频繁的入栈出栈,CPU啥也别干了。
- 缺少硬件滤波: 输入捕获自带数字滤波,外部中断可没有。信号稍微有点毛刺,你就得在软件里做消抖,麻烦。
那外部中断什么时候用?我遇到过一种情况:做轮速信号的“缺失齿”检测。比如某个齿故意少了一个,用来做基准位置。这时候用外部中断检测一个超长周期,反而比输入捕获更直观。
3.3 比较器与ADC:处理模拟信号的另一种思路
前面讲的都是方波信号。但有些轮速传感器输出的是正弦波,或者调理电路没做迟滞比较,信号还是模拟量。这时候怎么办?
两个选择:
- 片内比较器: 很多MCU内部集成了模拟比较器。你可以把轮速信号接到比较器正端,负端接一个可调的参考电压(DAC输出或者外部电阻分压)。比较器输出就是干净的方波,然后送给TIM输入捕获。
- ADC采样: 用ADC直接采正弦波,然后在软件里做峰值检测或过零检测。这方法精度高,但计算量大,一般用在高端域控或ADAS系统里。
我个人的经验是:能用比较器就别用ADC。ADC采样率再高,也有采样间隔和转换时间。而比较器是纯硬件响应,延迟只有几十纳秒。对于轮速这种实时性要求高的信号,比较器更靠谱。
配置比较器时,有个参数叫“迟滞”。我建议至少设置10mV以上的迟滞,防止信号在阈值附近抖动。我曾经遇到过因为迟滞设得太小,比较器输出在过零点来回跳,导致轮速数据忽高忽低。后来把迟滞调到30mV,世界清净了。
3.4 TIM的输入滤波与分频:细节决定成败
回到输入捕获。TIM模块里有两个容易被忽略的参数:输入滤波和输入分频。
| 参数 | 作用 | 我的建议 |
|---|---|---|
| 输入滤波 | 对输入信号进行连续采样,只有连续N个采样值一致才认为信号有效 | 根据信号质量设置,一般2-4个采样周期即可。太大会引入延迟。 |
| 输入分频 | 每N个有效边沿才触发一次捕获 | 通常设为1(不分频)。除非你只想测平均周期。 |
输入滤波的原理,说白了就是“防抖”。它用TIM的时钟去反复确认信号是不是真的变了。比如你设置滤波长度为4,那信号必须连续4个时钟周期都是高电平,才认为这是一个有效的上升沿。
这个功能在实车上特别有用。因为轮速传感器的线束很长,容易耦合进干扰。有了硬件滤波,很多毛刺在源头就被干掉了,不用软件再费劲。
3.5 总结一下硬件接口的选择
好了,咱们把几种方式捋一捋:
- 输入捕获: 首选方案。精度高、开销小、自带滤波。适合绝大多数轮速采集场景。
- 外部中断: 备选方案。适合简单应用或缺失齿检测。注意EMC干扰。
- 比较器+输入捕获: 处理模拟信号的黄金组合。比ADC更实时、更省资源。
- ADC采样: 高精度方案。适合需要分析波形细节的场景,但计算量大。
我个人在量产项目里,90%的情况都是用“调理电路+输入捕获”的组合。剩下的10%,要么是传感器输出正弦波需要比较器,要么是客户非要ADC数据做诊断。
下一章,咱们就聊聊怎么把这些硬件采集到的原始数据,变成稳定可靠的轮速值。那里面坑更多,但搞明白了,你就真正入门了。