问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

TIM编码器测速技术详解

创作时间:
作者:
@小白创作中心

TIM编码器测速技术详解

引用
CSDN
1.
https://blog.csdn.net/m0_74093370/article/details/145950191

TIM编码器测速技术是嵌入式系统中常用的位置和速度检测方法。本文将详细介绍编码器接口的工作原理、设计逻辑、工作模式以及具体实现代码,帮助读者深入了解这一技术的核心内容。

编码器接口简介

  • Encoder Interface 编码器接口
  • 编码器接口可接收增量(正交)编码器的信号,根据编码器旋转产生的正交信号脉冲,自动控制CNT自增或自减,从而指示编码器的位置、旋转方向和旋转速度
  • 每个高级定时器和通用定时器都拥有1个编码器接口
  • 两个输入引脚借用了输入捕获的通道1和通道2
    当编码器两个相的位置如图时为正向或者反相。

编码器测速的实质:

实质:测频法测正交脉冲的频率
CNT计次,然后每隔一段时间去一次计次,其实是测频法的思路
如果一个定时器配置成了编码机接口模式,则基本干不了其他活,C8T6芯片只有(TIM1、TIM2、TIM3、TIM4,4个定时器,故最多只能接4个编码器,接完后就没定时器可以用了

用正交信号的好处:

  • 正交信号精度更高,因为A、B相都可以计次,相当关于计次频率提高了一倍
  • 其次正交信号可以以抗噪声,因为正交信号两个信号必须是交替跳变的,可以设计一个抗噪声电路,如果一个信号不变,另一个信号连续跳变,也就是产生了噪声,这时计次值是不会变化的

编码器接口的设计逻辑

首先把A相和B相的边沿作为计数器的计数时钟(此时不使用内部时钟了,编码器相当于外部时钟),出现边沿信号时就计数自增或自减,增还是减由另一相的高低电平决定。所以这是一个硬件自动执行的过程。当每个相的边沿产生变化后,计数器CNT就会增加或者减少。

定时器中的编码器

编码器的输入是CH1,CH2。输出相当于是从模式控制器,控制CNT计数的控制速度和计数方向。 编码器接口有使用CH1和CH2的输入捕获滤波器和边沿检测,没有使用后面的是否交叉、预分频器、CCR寄存器与编码器接口无关。
流程:如果出现了边沿信号,并且另外一相为正转,则控制CNT自增。否则控制CNT自减。
ARR为65535 正转最大值是65535。
那么反转直接将无符号数据改为有符号对应的 65534就是 -1

编码器接口基本结构

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

图中TI1FP1信号就是A相,TI2FP2信号就是B相。中间相对信号的电平就是另一相的电平。仅在TI1计数就是在A相边沿计数,B相边沿变化无效。另外两个同理。这就是三个模式。
计数就是CNT根据边沿信号增加或者减少。

实例

图中列举了一个实例。采用的TI1和TI2都计数的模式。
图中也展示了抗噪声的原理,当产生噪声后并不是不计数了,而是通过我们的计数逻辑可以将错误的纠正回来。
上图时TI1反相TI2不反相的图。
TI1反相:输入从通道1进来以后,在极性选择部分,在使用输入捕获的时候这里是边沿极性的选择来触发输入捕获。但是此时上升和下降边沿我们都需要。所以此时就不再是边沿的极性的选择。而是高低电平的选择。在不反相的时候,是直接接到编码器接口的。反相后接了一个非门,此时TI1输出的信号和输入的信号就是相反的。所以图中要把TI1的电平反转一下再对照表格选择才是对的。
如果接一个编码器发现加减数的方向反了,此时就可以反转一下极性来控制。
编码器接口相当于一个带有方向选择的外部时钟。

代码

使用定时器3的通道 1 和 2 。
第一步:RCC开启时钟,开启GPIO和定时器的时钟
第二步:配置GPIO,PA6和PA7配置成输入模式
第三步:配置时基单元,预分频器选择不分频,自动重装,一般给最大65535,只需要给CNT执行计数即可
第四步:配置输入捕获单元(只有滤波器和极性两个参数)
第五步:配置编码器接口模式(调用库函数)
最后,调用TIM_Cmd开启定时器

void TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode,
                                uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity);
  

定时器编码接口配置函数。
第一个参数选择定时器,第二个参数选择编码器模式(计数方式,TI1计数或者TI2计数,或者两个都计数,)第三个和第四个参数是IC1和IC2的极性,就是是否反向。

void Encoder_Init(void)
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
        
    //编码器接口的实质是一个带方向控制的外部时钟,故内部时钟没用
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//此时计数方向被编码器托管所以这个参数无用
    TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;		//ARR计数范围最大,且方便换算为负数
    TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;		//PSC不分频
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
    
    //配置输入捕获单元
    TIM_ICInitTypeDef TIM_ICInitStructure;
    TIM_ICStructInit(&TIM_ICInitStructure);//赋一个初始值
    TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
    TIM_ICInitStructure.TIM_ICFilter = 0xF;
    //参数重复,在TIM_EncoderInterfaceConfig中也有配置//TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//高低电平极性不反转
    TIM_ICInit(TIM3, &TIM_ICInitStructure);//调用后就写入硬件寄存器,故结构体可以继续使用
    TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
    TIM_ICInitStructure.TIM_ICFilter = 0xF;
    //参数重复,在TIM_EncoderInterfaceConfig中也有配置//TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//高低电平极性不反转
    TIM_ICInit(TIM3, &TIM_ICInitStructure);
    TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
    TIM_Cmd(TIM3, ENABLE);
}
int16_t Encoder_Get(void)
{
    return TIM_GetCounter(TIM3);
}
  

上述代码就是编码器测编码电机的代码,但是此时只是得到了CNT的值,并没有得到速度。所以只需要在设置一个定时器中断,每隔一段时间读取CNT的值,然后计算速度即可。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号