2. STM32定时器编码器模式:原理、配置与实战

大家好,我是老周。今天咱们聊聊STM32定时器的一个特殊功能——编码器模式。说实话,我第一次接触这个功能时,也觉得挺绕的。但搞明白之后,你会发现它其实很巧妙。

2.1 定时器编码器模式原理

先说说为什么需要这个模式。你想想看,传统的编码器读取方式,要么用外部中断,要么用GPIO轮询。这两种方式都有问题——中断太频繁会拖累系统,轮询又浪费CPU。STM32的定时器编码器模式,说白了就是让硬件自己搞定这一切。

它的核心思想是:把定时器的计数器当作一个位置累加器。编码器每转一个脉冲,计数器就加1或减1。方向由两路信号的相位差决定。

关键点:定时器编码器模式本质上是一个硬件正交解码器。它直接读取编码器的A、B两相脉冲,自动判断方向并更新计数值。

我在一个伺服电机项目里用过这个模式。当时电机转速很高,如果用中断读编码器,CPU基本就废了。换成定时器编码器模式后,CPU占用率从35%降到了不到2%。嗯,效果立竿见影。

2.2 TI1与TI2配置详解

TI1和TI2,其实就是定时器的两个输入通道。TI1对应通道1(CH1),TI2对应通道2(CH2)。编码器的A相接TI1,B相接TI2。

配置时要注意什么?我建议你记住这个口诀:TI1和TI2必须配置为输入模式,且要开启滤波

为什么需要滤波?因为编码器在低速转动时,信号可能会有抖动。如果不滤波,计数器会乱跳。我曾经在一个项目里吃过这个亏——编码器静止时,计数值居然在±3之间来回跳。后来加了滤波,问题就解决了。

个人经验:滤波时间建议设为2-4个定时器时钟周期。太短了没效果,太长了会丢失高速脉冲。我一般用3个时钟周期,兼顾了稳定性和响应速度。

配置代码大致是这样的:

// 以TIM3为例,配置编码器模式
TIM_EncoderInterfaceConfig(TIM3, TIM_ENCODERMODE_TI12, 
                           TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
// 第一个参数:定时器句柄
// 第二个参数:编码器模式(TI1和TI2都参与计数)
// 第三、四个参数:TI1和TI2的极性(上升沿触发)

这里有个细节:极性配置。如果你发现编码器正转时计数器反而减小,那就把其中一个通道的极性取反。比如把TI1的上升沿改成下降沿,方向就反过来了。

2.3 计数方向与分辨率

计数方向由编码器的A、B相位差决定。A相领先B相90度,就是正转;B相领先A相90度,就是反转。定时器内部会自动判断,你只需要读CNT寄存器的值就行。

分辨率这块,很多人容易搞混。我简单解释一下:

  • 1倍频(TI1或TI2单边沿计数):每个脉冲只计一次。分辨率最低,但计数频率最高。
  • 2倍频(TI1和TI2双边沿计数):每个脉冲计两次。分辨率翻倍,但计数频率减半。
  • 4倍频(TI1和TI2的上升沿和下降沿都计数):每个脉冲计四次。分辨率最高,但计数频率最低。
模式 每转脉冲数(PPR) 实际分辨率 最大计数频率
1倍频 1000 1000 定时器时钟/2
2倍频 1000 2000 定时器时钟/4
4倍频 1000 4000 定时器时钟/8

我个人习惯用4倍频模式。虽然计数频率低一些,但分辨率高,位置控制更精准。你想想看,一个1000线的编码器,用4倍频就能达到4000的分辨率,相当于每转能检测到4000个位置。对于大多数应用来说,这个精度足够了。

注意:4倍频模式下,定时器的最大计数频率会降低。如果你的电机转速特别高(比如超过10000转/分),建议用2倍频或1倍频。否则可能会丢脉冲。

我曾经在一个高速主轴项目里踩过这个坑。电机转速12000转/分,编码器1000线,用4倍频模式。结果一跑起来,计数值就乱套了。后来换成2倍频,一切正常。嗯,这就是经验教训。

2.4 核心逻辑流程图

下面我用一张SVG图来展示定时器编码器模式的核心逻辑。这张图我画了好几次,力求简洁明了。

定时器编码器模式核心逻辑 编码器A相 编码器B相 TI1输入捕获 TI2输入捕获 相位差判断 A领先B → 正转 B领先A → 反转 CNT ±1 编码器模式工作流程:A/B相 → 输入捕获 → 相位判断 → 计数器增减 模式选择 • 1倍频:只检测TI1或TI2的上升沿 • 2倍频:检测TI1和TI2的上升沿 • 4倍频:检测TI1和TI2的上升沿和下降沿

这张图把整个流程串起来了。编码器的A、B相进入定时器的输入捕获通道,然后硬件自动判断相位差,最后决定计数器是加1还是减1。整个过程不需要CPU干预,这就是硬件解码的魅力。

2.5 避坑指南

最后,我总结几个容易踩的坑:

  • 计数器溢出:定时器的CNT寄存器是16位的(部分型号是32位),最大值65535。如果编码器转的圈数太多,计数器会溢出。解决办法是开启定时器的更新中断,在中断里记录溢出次数。
  • 初始化时清零:每次启动编码器模式前,记得把CNT寄存器清零。否则会带着上次的残留值,导致位置错误。
  • 不要同时用PWM输出:定时器编码器模式和PWM输出功能是冲突的。同一个定时器不能既当编码器输入,又当PWM输出。我见过有人这么干,结果编码器读数完全不对。

小技巧:调试时,可以用一个LED来指示方向。正转时亮绿灯,反转时亮红灯。这样不用看串口数据,一眼就能知道编码器工作是否正常。

好了,关于定时器编码器模式,今天就聊这么多。这个功能用好了,能省不少CPU资源。下次咱们聊聊怎么用DMA来搬运编码器数据,实现零CPU占用的数据采集。


公众号:蓝海资料掘金营,微信deep3321