2.18 TIM编码器接口(定时器第四部分)

导语

本次程序和我们之前写的旋转编码器计次的代码实现的功能是一样的,本质上都是旋转编码器计次,只不过这个代码是通过定时器的编码器接口,来自动计次的,而我们之前的代码是通过触发外部中断,然后在中断函数中手动进行计次,使用编码器接口的好处就是节约软件资源,如果使用外部中断来计次,那当电机高速旋转时,编码器每秒产生成千上万个脉冲,程序就得频繁进行中断,然后进入中断之后,完成的任务又只是简单的加一减一,这时我们的软件资源就被这种简单又低级的工作占用了。所以对于这种需要频繁执行,操作又比较简单的任务,一般我们都会设计一个硬件电路模块来自动完成。

那我们本节这个编码器接口,就是来自动给编码器进行计次的电路。如果我们每隔一段时间取一下计次值,就能得到编码器旋转的速度了。

这里的编码器测速一般应用在电机控制的项目上,使用PWM驱动电机,再使用编码器测量电机的速度,然后再用PID算法进行闭环控制,这是一个比较常见的使用场景。

一般电机旋转速度比较高,会使用无接触式的霍尔传感器或者光栅进行测速,我们这里为了方便,就使用触点式旋转编码器来进行演示。电机旋转就用人工旋转来模拟。

编码器接口简介

编码器接口英文是Encoder Interface 。

编码器接口可接收增量(正交)编码器的信号,什么是正交编码器?

就是像这样,输出两个方波信号,相位相差90度,超前90度或者滞后90度,分别代表正转和反转,这就是正交编码器。

编码器接口的工作流程是什么?

编码器接口可以根据编码器旋转产生的正交信号脉冲,自动控制CNT自增或自减,从而指示编码器的位置、旋转方向和旋转速度。

就是接收正交信号,自动执行CNT的自增或自减。这个编码器接口其实就相当于一个带有方向控制的外部时钟,他同时控制着CNT的计数时钟和计数方向,这样的话,CNT的值就表示了编码器的位置。如果我们每隔一段时间取一次CNT的值,再把CNT清零,那么每次取出来的值就代表了编码器的速度。这边编码器测速实际上就是测频法测正交脉冲的频率,只不过这个编码器接口更高级,他能根据旋转方向,不仅能自增计次,还能自减计次,是一个带方向的测速。

每个高级定时器和通用定时器都拥有1个编码器接口。 这个编码器接口的资源还是比较紧张的,如果一个定时器配置成了编码器接口模式,那它基本上就干不了其他活了,我们这个C8T6芯片只有TIM1、2、3、4,这4个定时器,最多只能接4个编码器,而且接完4个编码器,就没有定时器可以用了。所以如果你编码器比较多的话,需要考虑一下这个资源够不够用。不过实在还不行的话,可以使用外部中断来接编码器的,这样就是用软件资源来弥补硬件资源了。所以这里可以看出,硬件资源和软件资源是互补的。

两个输入引脚借用了输入捕获的通道1和通道2,通道3和通道4不能接编码器。

正交编码器

正交编码器一般可以测量位置,或者带有方向的速度值,他一般有两个信号输出引脚,一个是A相,一个是B相。

这个可以看一下我们之前写的编码器相关的内容

当编码器的旋转轴转起来时,A相和B相就会输出这样的方波信号,转的越来,这个方波的频率就越高,所以方波的频率就代表了速度,我们取出任意一相的信号来测频率,就能知道旋转速度了。但是只有一相的信号,无法测量旋转方向,因为无论正转还是反转,它都是这样的方波,想要测量方向,还必须要有另一根线的辅助。当正转时,A相提前B相90度,反转时,A相滞后B相90度。

编码器接口的设计逻辑就是,首先把A相和B相所有的边沿作为计数器的计数时钟,出现边沿信号时,计数器就自增或自减,然后到底是增还是减呢?

这个计数的方向由另一相的状态来确定,当出现某个边沿时,我们判断另一相的高低电平,如果对应的另一相的状态出现在上面这个表里,那就是正转,计数自增。反之,另一相的状态出现在下面这个表里,那就是反转,计数自减,这样就实现编码器接口的功能了。这也是我们STM32定时器编码器接口的执行逻辑。

编码器接口电路

编码器的输入部分:

这里编码器接口有两个输入端,分别要接到编码器的A相和B相。可以看出编码器的两个引脚,借用了输入捕获单元的前两个通道,所以最终编码器的输入引脚就是定时器的CH1和CH2这两个引脚上,CH3和CH4与编码器接口无关。其中CH1和CH2的输入捕获滤波器和边沿检测,编码器接口也有使用,但是后面的是否交叉、预分频器和CCR寄存器与编码器接口无关。

编码器的输出部分:

编码器的输入部分其实就相当于从模式控制器了,去控制CNT的计数时钟和计数方向。如果出现了边沿信号,并且对应的另一相的状态为正转,则控制CNT自增,反之自减。主义在这里我们之前一直在使用的72MHz内部时钟,和我们在时基单元初始化时设置的计数方向,并不会使用,因为此时计数时钟和计数方向都处于编码器接口托管的状态。计数器的自增或者自减受编码器控制。

编码器接口基本结构

输入捕获的前两个通道通过GPIO口接入编码器的A、B相,然后通过滤波器和边沿检测极性选择,产生TI1FP1和TI2FP2,通向编码器接口。

编码器接口通过预分频器控制CNT计数器的时钟,同时编码器接口还根据编码器的旋转方向,控制CNT的计数方向。

编码器正转时,CNT自增,反转时,CNT自减。

另外这里ARR也是有效的,一般我们会设置ARR为65535最大量程。这样的话,利用补码的特性,很容易得到负数。

比如CNT初始为0,我正转,CNT自增,0、1、2、3、4、5、6、7等等,这都没问题;但是我反转呢?CNT自减,0下一个数就是65535,接着是65534、65533等等,这里负数不应该是-1、-2码?65535是不是就出问题了?但是没关系,我们会做一个操作,直接把这个16位的无符号数转换为16位的有符号数,根据补码的定义,65535就对应-1,65534就对应-2等等,这样就可以直接得到负数,非常方便。这就是我们读出数据得到负数的一个小技巧。

编码器接口的三种工作模式

这个表,描述的就是我们刚才说的,编码器接口的工作逻辑,这里TI1FP1和TI2FP2接的就是编码器的A、B相。

在A相和B相的上升沿或者下降沿触发计数,分为了三种模式,其实就还是对应的那个表。

一般我们都会使用“在TI1和TI2上计数”,因为这个模式精度更高。

编码器接口实例图

实例1(两引脚都不反相)

这个图里就是使用了两个引脚的边沿都计数的模式。

其中这部分就是展示正交编码器的抗噪声的原理了,在这里TI2没有变化,但是TI1却跳变了好几次,这不符合正交编码器的信号规律,正交信号,两个信号交替变化,就像人走路一样,先迈左腿再迈右腿再左腿再右腿,这里就是右腿没动,左腿连续走了好几步,显然这个左腿的动作是一个毛刺信号,而通过我们上面这个表的逻辑,就可以把这种一个腿没动,另一个腿连走好几步的噪声过滤掉。这里如果出现了一个引脚不变,另一个引脚连续跳变多次的毛刺信号,计数器就会加、减、加、减来回摆动,最终计数值还是原来的那个数,并不受毛刺噪声的影响,这就是正交编码器抗噪声的原理。

实例2(TI1反相、TI2不返相)

TI1反相是什么意思?

TI1、TI2进来,都会经过这个极性选择的部分,在输入捕获模式下,这个极性选择是选择上升沿有效还是下降沿有效的,但是根据我们刚才分析,编码器接口显然始终都是上升沿和下降沿都有效的,上升沿和下降沿都需要计次,所以在编码器接口下,这里就不再是边沿的极性选择了,而是高低电平的极性选择,如果我们选择上升沿的参数,信号就是直通过来,高低电平极性不反转,如果选举则下降沿参数,信号就是通过一个非门进来,高低电平极性反转。所以这里就会有两个控制极性的参数。选择这里要不要加个非门,反转一下极性。

输入信号极性反相之后,如果你直接对照上面的表,得到的计数方向就是错误的。

所以我们应该把TI1的信号取反,再查表才对。

我们对照上面的实例1,可以发现这两个图的计数方向是相反的,这有什么用呢》比如你接了编码器,发现它的数据加减方向反了,你想要正转结果它自减,这时就可以调整一下极性,把任意一个引脚反相,就能反转计数方向了。