一、简介

Encoder Interface编码器接口

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

每个高级定时器和通用定时器都有1个编码器接口;

两个输入引脚借用了输入捕获的通道1和通道2;

二、基础原理

1、正交编码器信号

增量式正交编码器输出A相、B相。

正向旋转:A先跳变,随后B跳变;

反向旋转:B先跳变,随后A跳变;

定时器硬件自动识别相位先后,自动增减CNT寄存器,无需软件判断方向。

2、定时器编码器模式

STM32F1系列定时器编码器模式由TIM_EncoderMode配置,3种模式:

      模式一:TIM_EncoderMode_TI1:仅检测TI1边沿,只在A相跳变计数;

      模式二:TIM_EncoderMode_TI2:仅检测TI2边沿,只在B相跳变计数;

      模式三:TIM_EncoderMode_TI12:TI1+TI2双边沿都计数(4倍频),比较常用,A、B上升沿+下降沿全部触发计数→分辨率x4;F103系列只有TIM1/TIM2/TIM3/TIM4支持编码器模式,TIM5/TIM6/TIM7不支持。

        核心逻辑:检测到某一相边沿→立即读取另一相此刻电平→根据电平决定CNT+1(向上计数)还是CNT-1(向下计数)。

        相对信号的电平指的是:

        TI1FP1对应TI2:TI1发生跳变,参考信号是TI2电平;

        TI1FP2对应TI1:TI2发生跳变,参考信号是TI1电平;

即:当TI1FP1出现跳变沿时,硬件读取TI2FP2当前电平;当TI2FP2出现跳变沿时,硬件读取TI1FP1当前电平。

举例:标准正转时序:A↑→B↑→A↓→B↓,对照模式三,4倍频查表得知:

A上升沿,此时B=0(低电平)→向上计数++;

B上升沿,此时A=1(高电平)→向上计数++;

A下降沿,此时B=1(高电平)→向上计数++;

B下降沿,此时A=0(低电平)→向上计数++;

一圈4次计数,即4倍频,反转时波形顺序颠倒,每次边沿查表都会触发向下计数,如下:

反转时序:B↑→A↑→B↓→A↓

B上升沿,此时A=0(低电平)→向下计数--;

A上升沿,此时B=1(高电平)→向下计数--;

B下降沿,此时A=1(高电平)→向下计数--;

A下降沿,此时B=0(低电平)→向下计数--;

再举例:仅TI1计数(TIM_EncoderMode_TI1)

规则:只有A相跳变才计数,B相任何变化直接无视。

同样正转波形:A↑→B↑→A↓→B↓

A上升沿,此时B=0(低电平)→向上计数++;

B上升沿→忽略不计数;

A下降沿,此时B=1(高电平)→向上计数++;

B下降沿→忽略不计数;

一个周期只+2,即2倍频;

3、工作模式表格注意点

1)日常一律使用TIM_EncoderMode_TI12,模式三,4倍频;

2)如果旋转时计数方向反了,2种修改方案:

方案一:硬件互换A、B两相接线;

方案二:软件修改TIM_EncodeInterfaceConfig的极性参数(翻转TI1或者TI2);

3)表格前提条件:A、B两相不会同时跳变。正常正交编码器本身满足,电机干扰出现同时跳变会造成计数误差,需要加大输入滤波ICFilter。

4、与输入捕获的关系

1)硬件结构

TIM的CHI1、CH2引脚,硬件本就是输入捕获通道,引脚→滤波器(ICFilter)→极性选择(CCxP)→TI1FP1/TI2FP2。编码器没有独立的引脚通路,需要共用捕获的前端电路。滤波、极性反转、信号选通,都是输入捕获的配置寄存器,所以都用到TIM_ICInit函数,只是不用捕获功能。

2)配置区别

TIM_ICInit:只配置信号前端(滤波、极性、直通TI),只负责:把引脚(比如TIM3的复用引脚PA6/PA7)的原始信号,处理成干净的TI1FP1、TI2FP2,传给后续编码器逻辑;TIM_ICPSC_DIV1在编码器模式下无效,赋值1即可。TIM_EncoderInterfaceConfig函数开启编码器计数逻辑,定时器内部切换成正交编码器模式,不再用输入捕获,而是根据A/B相位差自动加减CNT;

3)易混淆关键点

普通输入捕获:检测边沿,存捕获值、进中断,测脉冲周期/频率,是一套信号预处理模块。

编码器模式:关闭捕获逻辑,只用捕获的信号预处理电路,硬件自动累加CNT,不需要捕获中断等,是一个计数判断模块。

5、输入模式选择

编码器引脚浮空输入、上拉输入都可以用,上拉输入是工程常用方案。

浮空:电平由外部编码器决定,推挽输出编码器最常用,自带强高低电平驱动,浮空完全适配,理论上标准接法。但编码线很长、走线干扰大时,悬空易引起杂波误计数;

内部上拉:1)编码器NPN集电极开路/OC输出必须用上拉,否则静止时引脚电平不确定。

2)不会改变A/B相的相位先后,不影响正反转判断、计数倍率。

3)兼容性强:不会是推挽输出还是开路输出编码器,内部上拉均兼容。

3)抗干扰强:线束长、电磁干扰时,上拉能固定静态电平,减少毛刺导致的多计数。

4)必须浮空:编码器已经外接了上下拉电阻,如果再开内部上拉,会分压改变电平阈值。

三、代码

1、Encoder.c文件

#include "stm32f10x.h"                 

void Encoder_Init()
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,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 ;
	
	TIM_TimeBaseInitTypeDef TIM_InitStructure;
	TIM_InitStructure.TIM_ClockDivision =TIM_CKD_DIV1;
	TIM_InitStructure.TIM_CounterMode =TIM_CounterMode_Up;
	TIM_InitStructure.TIM_Period =65536-1;
	TIM_InitStructure.TIM_Prescaler =0;
	TIM_InitStructure.TIM_RepetitionCounter =0;
	TIM_TimeBaseInit(TIM3,&TIM_InitStructure);
	
	TIM_ICInitTypeDef IC_InitStructure;
	IC_InitStructure.TIM_Channel =TIM_Channel_1;
	IC_InitStructure.TIM_ICFilter =0xF;
	IC_InitStructure.TIM_ICPolarity =TIM_ICPolarity_Rising;
	IC_InitStructure.TIM_ICPrescaler =TIM_ICPSC_DIV1;
	IC_InitStructure.TIM_ICSelection =TIM_ICSelection_DirectTI;
	TIM_ICInit(TIM3,&IC_InitStructure);
	IC_InitStructure.TIM_Channel =TIM_Channel_2;
	TIM_ICInit(TIM3,&IC_InitStructure);
	//编码器模式最终确定极性,覆盖上面IC里的极性配置
	TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);
		
	TIM_Cmd(TIM3,ENABLE);	
}

int16_t GetEncoderCounter()
{
	return TIM_GetCounter(TIM3);
}

2、Encoder.h文件

#ifndef __ENCODER_H
#define __ENCODER_H

void Encoder_Init();
int16_t GetEncoderCounter();

#endif

3、main函数

#include "stm32f10x.h"                 
#include "Delay.h"
#include "OLED.h"
#include "Encoder.h"
#include "Timer.h"
int16_t Counter;

int main()
{
	OLED_Init();
	Timer_Init();
	Encoder_Init();	
	OLED_ShowString(1,1,"Counter:");
	
	while(1)
	{		
		OLED_ShowSignedNum(2,1,Counter,5);
	}
}
void TIM2_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
	{
		Counter = GetEncoderCounter();
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
	}
}

4、代码补充说明

编码器测速一定要有定时中断:编码器CNT一直在累加,需要固定时间间隔读取计数值、算速度。

比如:10ms进一次中断,本次读CNT=500,清零CNT;代表10ms内编码器走了500个脉冲→换算速度,如果不使用定时中断,靠while循环读取,读取间隔不确定,速度算不准。

5、干扰(毛刺)的处理

编码器机械触点转动、齿轮咬合、导线受电磁干扰,会在正常跳变沿附近出现很多快速高低跳变的杂脉冲,即毛刺,TIM硬件会把每一次跳变都当成有效计数,计数器就会乱跳、多计数、正负来回跳、数值漂。

处理方案:

1、输入滤波ICFilter,寄存器TIM_CCMRx,0~15。短接线、干净环境:3~5;长线、电机旁边干扰大:8~15;

原理:连续N个定时器采样时钟都采到相同电平,才认定电平真的翻转,毛刺因持续时间短,采不到稳定电平,直接被过滤。采样时钟=定时器时钟(编码器PSC=0,72MHz)。ICF=0xF,需要连续15个采样周期电平不变,才判定电平真的翻转。

2、内部上拉:浮空输入时,毛刺易把悬空引脚电平拉乱,内部上拉将引脚电平钳在高电平,干扰不容易拉低电平,硬件层面减少毛刺产生。

3、硬件:编码器A/B线用屏蔽线,屏蔽层单端接地;走线尽量短,远离电机电源线、继电器大电流走线;引脚并联1000pF小电容到GND,RC滤波,吸收高频毛刺。

本文完!

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐