STM32外设学习--TIM定时器--编码器接口(程序)
上次我们完成了TIM定时器的最后一个功能,编码器接口,这些课我们来编写这个定时器编码的模式的代码。还是先说一下,建议各位学习的还是养成写博客习惯,就当记录笔记了,当自己写的文章上榜时候还是优点小激动的,虽然含金量少,但是也能督促了。


一.硬件接线图

我们来看我们的接线图,这个接线图,和我们外部中断那个接线图类似,我们把旋转编码器插在面板版左面,VCC和GND接在电源正负极,下面的A相输出,我们接在PA6引脚,B相输出接在PA7引脚。这里的PA6和PA7引脚可以交换一下,都是可以的就是正传和反转的极性不同。
但是PA6和PA7这两个引脚不能随意切换

我们看一下引脚定义,PA6和PA7是接在TIM3的CH通道1和CH通道2。我们计划用TIM3接编码器,所以需要接在PA6和PA7这两个引脚。其他定时器的话也是需要参考这个表。接在对应的CH1和CH2的位置。
二.代码编写
1.了解函数

我们先复制一下,定时器定时中断的代码。

添加编码器的代码模块

添加好我们的文件。

按照我们的文件流程进行配置。

定时器编码器接口配置。
2.编写程序


因为前面的代码一样,所以我们直接复制输入捕获的就好。然后我们逐条修改
![]()
因为我们用的是PA6和PA7所以我们要对两个端口进行初始化。
![]()
GPIO的模式,依旧是上拉模式,这里可以选择,上拉,下拉,浮空模式。我们可以看一下接在这个端口的外部模块的默认电平,如果外部模块默认输入高电平,我们就选择上拉输入,反之选择下拉输入。和外部设别默认电平保持一致,防止打架。

这一行不需要了因为编码器接口会托管时钟,编码器接口就是一个带方向控制的外部时钟。
![]()
这个函数基本也没有用了,因为计数方向也是被编码器托管的,
![]()
满量程计数,因为这样子计数是最大的,并且方便转换负数。
![]()
预分频器的值我们给1-1,也就是0分频就是不分频,编码器的时钟直接驱动计数器。

接下来是输入捕获部分,我们可以看到,输入捕获部分没有完全用到,编码器接口,只是用来通道1和通道2的滤波器以及边沿极性选择。所以我们只需要配置这两部分参数即可。

在代码中也就是这两部分与函数无关。目前结构体值是不完整的,为了防止我们结构体初始化出现问题,我们需要给结构体一个初始化默认值。
![]()
用这个函数,给我门结构体赋一个初始值。

放在这里。

转到定义就可以看到,这些就是他给的默认的初始值。
![]()
来到这里,这里的上升沿并不代表上升沿有效。因为编码器接口都是,上升沿,下降沿都有效的。
这里的上升沿表示,高低电平极性不翻转。

也就是这里解释的TI1和TI2不进行反向。给上升沿就是不反向,给下降沿就是反向。

因为我们上面配置好了通道1,还需要对通道2进行配置,我们直接复制就好。

接下来我们初始化编码器接口。

第二个参数是选择编码器模式。可以选择下面的参数。
TI1仅在TI1计数。
TI2仅在TI2计数。
TI12在TI1和TI2一起计数。

对应我们这里三个模式。
我们选择TI12一起计数。

转到参数,我们可以看到IC1和IC2的极性了。选择Rising就是不反向,Falling就是反向。

我们可以看到,这两个参数和上面的两个参数是一样的,实际的效果呢就是一样的。这两个地方的参数,实际上是配置的同一个寄存器。

我们前面的配置就可以删掉了。因为后面配置过了,后配置的会把先配置的覆盖。

要记得,encode这个函数要在ic_init下面,否则encode就会被覆盖掉。

到这里发现整个ic_init只有一个滤波器参数有用了。

然后我们开启TIM3定时器。

写一个返回函数,我们先直接返回TIM3的值看一下。

这两个函数,放在这里进行调用。

编译一下,0错误0警告。

包含头文件,进行初始化。

先不断率刷新CNT的值并且在oled上显示一下。

编译下载之后,我们可以看到,显示的值变为4了。

我们编码器波形是有段落性的,A相产生一个脉冲,B相产生一个滞后90°的脉冲,是超前滞后取决于我们的正反转。我们看到编码器转动了一格,产生了两个上升沿两个下降沿,所以计次增加了4次。如果是电机的编码器,就不会有段落感了

当我们转到0之后,就会发现没有变为负数,而是变为65535,计数器反向溢出了。如果要显示我们的-1,我们就让uint 16_t,强制转换为int16_t就可以了。

直接把我们函数的返回值变为int16_t.。

记得.h文件也要修改。
![]()
并且主函数中改为能显示负数的OLED显示函数。

之后我们就可以看到向右的话,就变为了负数。
现在我们研究一下极性问题
现在向右转是自增,向左转是自减,如果不符合我们的预期,在硬件层面,我们可以把A和B这两根线换一下位置。

这样子向右转就是递减,向左转就是递增。

在软件层面,我们可以修改这两个参数的极性。把任意一个极性反转过来我们方向就更改过来了。
如果两个都反转,那么极性就会保持不变。
如果我们想要编码器测速的话,就可以在固定的闸门时间读取一次CNT,然后把CNT清。

修改一下我们的子函数。

主函数中延迟。因为手转的慢,所以我们给长一点,要是电机闸门可以给短一点,防止技术溢出。

我们慢速转速度比较小,

快速转则变得比较大。如果主函数没有其他程序可以这么干,有的话需要用到定时中断,让我们可以不在主函数中延时过长的时间。
![]()
定义一个变量。

让我们的speed等于返回的计数值。

这是我们主程序的修改。

发现可以测速,到这里我们的程序就完成了。
zhezhe

