第四章 TIM模块详解:TIM通道结构、输入捕获模式、滤波与消抖

好,咱们进入TIM模块。说实话,TIM在GTM里是个特别实在的模块。它不像TOM那样要输出PWM,也不像ATOM那样搞复杂的序列。TIM的核心任务就一个——把外部信号读进来,搞清楚它是什么情况

我刚开始接触TC3xx时,觉得TIM不就是个输入捕获嘛,有啥好讲的?后来做项目才发现,TIM的滤波和消抖功能,才是真正体现功力的地方。你想想看,如果信号进来全是毛刺,你捕获到的数据根本没法用。

4.1 TIM通道结构概览

每个TIM模块有8个通道,每个通道都是独立的。我习惯把TIM通道想象成一个信号处理流水线

  1. 信号从外部引脚进来
  2. 经过滤波和消抖处理
  3. 进入捕获逻辑
  4. 最终产生时间戳数据

每个通道的核心寄存器就那么几个:

寄存器功能我常用的配置
TIM_CHx_CTRL控制寄存器,配置模式、边沿、滤波等这个寄存器我几乎每个项目都要反复调
TIM_CHx_IRQ中断控制一般用上升沿触发中断
TIM_CHx_ECNT事件计数器调试时看这个值就知道信号有没有进来
TIM_CHx_CNTS捕获的时间戳核心数据,做速度测量全靠它

嗯,这里要注意:TIM通道的时钟源是CMU_CLK0,默认频率是fGTM/2。我有个项目因为没注意时钟分频,导致捕获精度差了整整一倍,排查了半天才发现。

4.2 输入捕获模式

输入捕获,说白了就是记录信号边沿到来的时刻。TIM支持三种捕获模式:

  • 单次捕获:只捕获一次,适合测量单个脉冲宽度
  • 连续捕获:每次边沿都捕获,适合测量周期
  • 多事件捕获:可以同时捕获上升沿和下降沿,适合测量占空比

我一般用连续捕获模式做转速测量。举个例子,你要测一个风扇的转速:

// 配置TIM通道0为连续捕获模式,上升沿触发
TIM_CH0_CTRL.B.MODE = 0x02;  // 连续捕获
TIM_CH0_CTRL.B.EDGE = 0x01;  // 上升沿
TIM_CH0_CTRL.B.DSL = 0x01;   // 使能捕获

// 使能中断
TIM_CH0_IRQ.B.EN = 1;

// 在中断服务函数中读取时间戳
uint32_t timestamp = TIM_CH0_CNTS.U;
// 计算转速:转速 = 60 / (timestamp * 时钟周期)

这里有个坑——连续捕获模式下,CNTS寄存器是只读的。你读一次,它就会自动清零。所以一定要在中断里第一时间把值读出来,不然就丢了。我曾经因为这个丢数据,查了整整一个下午。

关键点:TIM的捕获是基于GTM的系统时钟,精度可以达到一个时钟周期。但要注意,如果信号频率太高,超过了TIM的处理能力,就会丢事件。我一般建议信号频率不要超过fGTM/4。

4.3 滤波与消抖

这才是TIM模块的精髓。你想想看,实际工程中的信号哪有那么干净?电机启动时的干扰、按键按下时的抖动、通信线上的毛刺……如果不做处理,捕获到的数据全是错的。

TIM提供了两级滤波:

  • 第一级:边沿滤波(EDGE_FILTER)
  • 第二级:时间滤波(TIME_FILTER)

我习惯把第一级叫硬滤波,第二级叫软滤波。为什么这么叫?因为第一级是纯硬件实现的,不消耗CPU;第二级需要配合中断,会占用CPU时间。

4.3.1 边沿滤波(EDGE_FILTER)

边沿滤波的原理很简单:只有信号稳定超过N个时钟周期,才认为边沿有效。TIM支持1到32个时钟周期的滤波长度。

// 配置边沿滤波,滤波长度为8个时钟周期
TIM_CH0_CTRL.B.EDGE_FILTER = 0x03;  // 8个时钟周期
TIM_CH0_CTRL.B.EDGE_FILTER_EN = 1;  // 使能滤波

我在做汽车电子项目时,遇到过一种情况:信号线上有200ns左右的毛刺。当时我设了4个时钟周期的滤波(约100ns),毛刺就被滤掉了。但要注意,滤波长度设太大,会丢失真正的信号。这个平衡点需要根据实际信号质量来调。

我的经验:调试滤波参数时,先用示波器看信号质量。如果毛刺宽度是T,滤波长度设成1.5T到2T比较合适。别设太大,否则信号延迟会很明显。

4.3.2 时间滤波(TIME_FILTER)

时间滤波更高级一些。它不是简单地滤毛刺,而是基于时间窗口来判断信号是否有效。你可以设置一个时间窗口,只有在这个窗口内出现的边沿才被捕获。

这个功能在测量PWM占空比时特别有用。比如你要测量一个50Hz的PWM信号,可以设置时间窗口为20ms,这样就能避免其他干扰信号被误捕获。

// 配置时间滤波,窗口长度为1000个时钟周期
TIM_CH0_CTRL.B.TIME_FILTER = 0x01;  // 使能时间滤波
TIM_CH0_CTRL.B.TIME_FILTER_LEN = 1000;  // 窗口长度

注意:时间滤波和边沿滤波可以同时使用。但要注意,同时使用会增加信号延迟。我有个项目因为同时用了两级滤波,信号延迟了将近1ms,导致控制环路响应变慢。后来我只用了边沿滤波,效果反而更好。

4.4 实际应用中的避坑指南

做TIM开发这几年,我踩过的坑真不少。挑几个典型的说说:

  • 中断优先级:TIM中断优先级不要设太高,否则会影响其他实时任务。我一般设成中等优先级。
  • 时钟同步:如果多个TIM通道要同步捕获,记得用同一个时钟源。我有个项目因为用了不同时钟源,导致两个通道的时间戳差了十几个时钟周期。
  • 滤波参数调试:先在仿真器里看原始信号,再逐步加大滤波参数。别一上来就设最大值,那样信号延迟会让你怀疑人生。

我曾经在一个电机控制项目里,因为滤波参数设得太大,导致转速测量延迟了2ms。电机在低速时还好,一加速就振荡。后来我把滤波长度从16个时钟周期降到4个,问题就解决了。嗯,这个教训让我记住了——滤波不是越强越好,够用就行

4.5 小结

TIM模块看似简单,但用好了能解决很多实际问题。我个人觉得,掌握TIM的关键在于理解它的信号处理流水线——信号进来后,先滤波,再捕获,最后产生中断。每一步都有讲究,每一步都可能出问题。

下一章咱们讲TOM模块,那是输出PWM的核心。到时候你会发现,TIM和TOM配合起来用,能实现很多复杂的时序控制。