STM32外设学习--TIM定时器--编码器接口
我们上次学完了STM32TIM定时器的输入捕获,输出比较,定时,定时中断,这次我们来学习最后一个功能,编码器模式。
一.TIM编码器模式简介
1.简介
STM32F103C8T6的定时器编码器接口功能非常实用,它通过硬件自动处理正交编码器的脉冲和方向识别,大大简化了位置和速度测量的程序负担。下面这个表格汇总了其核心特性:
| 特性项目 | 说明 |
|---|---|
| 支持定时器 | 通用定时器:TIM2, TIM3, TIM4;高级定时器:TIM1, TIM8 |
| 使用通道 | 固定使用通道1 (TI1) 和通道2 (TI2),通道3和4不可用于编码器模式 |
| 编码器模式 | 模式1 (仅在TI1边沿计数)、模式2 (仅在TI2边沿计数)、模式3 (TI1和TI2边沿均计数) |
| 计数方向判断 | 硬件自动检测TI1和TI2的相位关系,自动控制CNT自增或自减 |
| 有效边沿 | 可通过极性设置选择上升沿、下降沿或双边沿触发 |
| 滤波功能 | 可配置输入滤波器,有效抑制信号抖动 |
| 计数器位数 | 16位 |
| 最大计数值 | 0 ~ 65535 (TIMx_ARR) |
2.配置要点与步骤
配置编码器接口时,可以参考以下步骤和要点:
-
GPIO配置:
将编码器的A相(TI1)和B相(TI2)信号引脚连接到定时器支持编码器模式的通道上(通常是CH1和CH2)。GPIO应配置为浮空输入或上拉输入模式。如果编码器是OC(集电极开路)输出,必须在硬件上确保有上拉电阻。 -
时基单元配置:
-
预分频器 (PSC):通常设置为0,即不分频-1。
-
自动重装载值 (ARR):决定了计数器的周期,通常设置为最大值65535以获取最宽的测量范围-1。这个值也决定了计数器溢出前的最大计数值。
-
-
编码器模式配置:
通过TIM_EncoderInterfaceConfig函数进行配置。-
模式选择:
-
TIM_EncoderMode_TI1:仅在TI1边沿计数。 -
TIM_EncoderMode_TI2:仅在TI2边沿计数
。 -
TIM_EncoderMode_TI12:在TI1和TI2的边沿都计数,可以实现4倍频,提高分辨率。例如,一个11线的编码器在此模式下每转可产生11 x 4 = 44个脉冲。
-
-
极性设置:可以为TI1和TI2分别选择极性(上升沿、下降沿)。若两者均设置为上升沿,则计数器会在两个信号的所有边沿(上升沿和下降沿)进行计数,这也是实现4倍频的一种方式
-
-
滤波器设置:
通过TIM_ICInitStructure.TIM_ICFilter配置输入捕获滤波器,可以有效抑制信号线上的噪声干扰,取值范围通常是0x0到0xF。 -
启动编码器接口:
完成配置后,使能定时器以启动编码器接口。在HAL库中,使用HAL_TIM_Encoder_Start()函数。
3. 数据读取与方向判断
-
读取计数值:直接读取定时器的计数器寄存器(CNT)即可获得当前的计数值。在HAL库中,可以使用
__HAL_TIM_GET_COUNTER(&htimx)函数读取。 -
判断旋转方向:通过检查定时器控制寄存器1(CR1)中的DIR位,或者使用HAL库提供的
__HAL_TIM_IS_TIM_COUNTING_DOWN(&htimx)宏来判断方向。返回0通常表示正向(递增),1表示反向(递减)。
4.注意计数器溢出与软件计数
STM32F103的定时器是16位的,最大计数值为65535在高速或长时间运行时,计数器可能会溢出。处理方法包括:
-
利用溢出中断:使能定时器的更新中断,在中断服务程序中对一个软件计数器(如
OverflowCount)进行增减。最终的计数值为:CurrentCount = (int16_t)TIMx->CNT + OverflowCount * 65536。 -
定期采样计算差值:在固定时间间隔(如10ms)内读取两次CNT值,其差值即为该时间段内的脉冲数,可用于计算速度,并能处理单次采样期间的计数器翻转问题。
使用定时器的编码接口,再配合编码器,就可以测量旋转速度和旋转方向了。这里编码器测速一般用在电机控制的项目上。使用PWM驱动电机,再使用编码器,测量电机速度。在用PID算法进行闭环控制。一般电机的旋转速度比较高,会使用无接触的霍尔传感器,以及光栅进行测速。我们用触点式的旋转编码器,进行模拟速度。
二.TIM编码器的结构
1.结构

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

如图就是向这样输出的两个方波信号,相位相差90°超前92°和滞后90°,分别代表正传和反转。
编码器接口可以根据编码器旋转,产生的正交信号脉冲。自动控制CNT自增或自减。从而指示编码器的位置,旋转方向和旋转速度。
2.例子
比如有一个编码器,有A,B两相接入到STM32的定时器的编码器接口,编码器接口,自动控制定时器,时基单元中的CNT计数器。进行自增或自减,比如初始化之后,CNT的值为0,然后编码器右转,CNT就++,右转产生一个脉冲,CNT就+1。比如右键产生十个脉冲停了下来,那么这个过程CNT就由0自增到10,停下来。
编码器左转,CNT就--,左转产生一个脉冲,CNT就-一次。比如编码器在左转产生5个脉冲,那么CNT就在原来10的基础上自减5停下来,这个编码器接口相当于一个,带有方向控制的外部时钟。
他同时控制着,CNT的计数方向和计数时钟。这样子的话CNT的值就表示了编码器的位置,如果我们每隔一段时间,取一次CNT的值,再把CNT清0,是不是每次取出来的值就表示了编码器的速度。
3.继续
每个通用定时器和高级定时器,只有一个编码器测速接口。只要这个定时器,设置为了编码器接口模式,那么他就不能进行其他的操作了。不过也可以用外部中断来接编码器,这样子就是用软件资源,来弥补硬件资源了。硬件资源和软件资源是互补的,硬件越多,软件越轻松。
比如PWM我们可以来个定时中断,然后再中断里手动计数,手动反转电平
输入捕获,可以来个外部中断,在中断里手动把CNT取出来,放在变量里。
编码器模式,也可以,直接定时中断,在终端里手动计数进行自增,自减。
4.正交编码器

正交编码器他有两个引脚,一般可以测量位置,或带有方向的速度,一般有两个输出引脚,一个是A相,一个是B相。
当我们编码器转动时候,A相和B相就会输出如图所示的方波信号,转的越快,方波的频率越高。所以方波的频率就代表了速度,我们取出任意一项的信号来测频率,就可以知道速度了。但是只有一项的信号无法测量旋转方向,因为无论正传还是反转,都是这样的方波。想要测量方向,还需要另一个线的辅助,比如我们的图片,当正传时候,A相提前B相90°,反转时A相滞后B相90°方向不是固定的,而是相对的,可以自己定义。
那么用正交信号有什么好处呢,那么就是A,B相都可以计次,相当于频率提高了一倍,让我们的精度更高。还可以抗噪声,因为正交信号两个信号必须是交替跳变的。

A相上升沿,对应B相低电平。
B相上降沿,对应A相高电平。
A相下降沿,对应B相高电平。
B相下降沿,对应A相低电平。

反转的话正好和正传相反。
所以我们编码器的逻辑就是,把A相和B相的所有边沿,作为计数器的计数时钟。出现边沿信号时,计数器就自增自减。到底是增还是减呢,计数的方向根据另一项的状态来确定。当出现某个边沿时。我们判断另一项的高低电平。如果对应的另一项状态出现在上面的表中,那么就是自增。反之另一项的状态出现在下面的表中就是自减。这样就能实现编码器的功能了。这也是我们STM32
定时器编码器接口的执行逻辑。那么接下来我们看一下这个定时器框图。
5.编码器接口电路结构

这里有两个编码器接口的输入端,分别要接到编码器的A相和B相。这里时两个网络标号,分别写的TI1FP1和TI2FP2。

对应的是这里。

可以看出,定时器编码器的接口的两个引脚,借用了输入捕获单元的前两个通道。所以最终编码器的输入引脚,就是定时器的CH1和CH2。
同时CH1和CH2的输入捕获滤波器和边沿检测,编码器也有使用,但是后面的是否交叉,预分频器,和CCR寄存器与编码器接口无关。这就是编码器接口的输入部分。
编码器接口的输出部分,就相当于,从模式控制器了。去控制CNT的计数时钟和计数方向。
简单来说,这里的输出流程,按照我们之前的那个表。如果出现了边沿信号,并且对应的另一相的状态为正传。则控制CNT的自增。否则控制CNT的自减。
我们一直使用的72MHz的内部时钟,和我们在时基单元,初始化时设置的计数方向并不会使用。
因为此时计数时钟和计数方向,都处于编码器接口托管状态。计数器的自增或自减,受编码器控制(向上计数,向下计数,中间对齐计数)。不会影响我们的计数方式。
这就是编码器接口的电路结构。
6.编码器接口基本结构

这个图就很清晰了,输入捕获的结构,通过GPIO接口,接入编码器的A,B相。通过滤波器和边沿检测,极性选择,产生TI1FP1和TI2FP2,通向编码器接口。编码器接口,通过预分频器,控制CNT计数的时钟。同时编码器接口,还根据编码器旋转方向,控制CNT的计数方向,
编码器正传时候CNT自增,编码器反转时CNT自减。另外这里ARR也是有效的,ARR的值我们一般设置为,65535最大量程。利用补码的特性很容易得到负数
因为正传的话是,0,1,2,3,4,5,6.
然后反转,6,5,4,3,2,1,0,65535,65534,65533等等。
这里我们因该让负数变为-1和-2,不因该是65535。但是不慌,我们可以进行一个操作,可以把16位的无符号数,转化为16位有符号数。根据补码的定义,65535对应-1,65534对应-2。
补码-1然后按位取反,就得到了源码,65535补码是,16个1,然后减去1个1,是是15个1和一个0,按位取反,就是15个0和一个一,这个一就是-1。
7.编码器接口工作逻辑表

这里的TI1FP1和TI2FP2接入的就是A相B相。到底是向上计数还是向下计数,取决于边沿信号发生时刻,另一相的电平状态。也就是我们表格中,相对信号的电平。

对比一下我们就知道,比如说A相上升沿,B相下降沿,对应就是向上计数。上面个就是单向计数。
一般我们会用下面的模式,因为下面的模式是双向计数,计数精度最高。
8.实例图
(1)两个引脚不反向
这是我们两个引脚不反向的图

这里使用两个引脚的边缘都计数的模式。

查表,当TI1上升沿到来,TI2为低电平,那么执行的是向上计数,此时CNT的值,向上+1。

这里就是我们正交编码器抗噪声的原因了,这里TI2没有变化,TI1变化了好几次,这不符合正交编码器的信号规律。(正交信号是两个信号交替变化,一个变完了另一个再变化)。
比如说TI1上升沿,TI2低电平,向上自增,然后TI1下降沿,TI2还是低电平,向下自减,这就把我们的噪声滤除了。因为一个引脚电平不变,另一个来回跳变,计数器就会+,-,+,-来回摆动,从而消除噪声。
(2)TI1反向TI2不反向的图

TI1反向的意思就是,我们可以看这个图,这里TI1和TI2进来,都会经过这个极性选择的部分,在输入捕获模式下,这个极性选择,是选择,上升沿有效,还是下降沿有效。根据我们刚才分析,编码器接口始终都是上升沿下降沿都有效的。上升沿下降沿都需要计次。
所以在编码器接口的模式下,这里就不是边沿的极性选择,而是高低电平的极性选择。
如果我们选择上升沿的参数,那么就是信号直通过来,高低电平信号不翻转,如果选择下降沿信号,那么输入信号就是通过一个非门进来,高低电平极性反转。

这就是TI1高低电平反转的情况下,TI1反向的图。
我们需要把TI1高低电平取反,这才是反向后给编码器的电平,然后在查表。
第一个装态,是TI1下降沿,TI2低电平,得到向下计数。这样子才是我们CNT计数器最终的计数。
(3)手册观看
最后看一下手册

这里是编码器接口的整体介绍。合理的观看手册可以帮助我们更好的理解,我们为什么这样子写程序。
