当前位置:首页 > 新型工业化 >定时器 编码器(定时器的编号)

定时器 编码器(定时器的编号)

上一篇文章介绍了定时器捕获输入脉冲的原理。该方法基于捕捉原理,手动切换上升沿和下降沿捕捉。计算脉冲宽度的过程原理比较清晰,但编程操作比较麻烦。

对于用于电机速度测量的正交编码器,测量速度时需要捕获2个脉冲。如果采用上一篇文章介绍的方法,编程会比较复杂。幸运的是,单片机的通用定时器有专用的正交编码器接口。只需配置相应的寄存器即可自动捕获并统计编码器输入的上下沿,对于编码器测速非常方便。

定时器 编码器(定时器的编号)

下面介绍一下定时器的编码器模式的使用:

1 正反转计数原理示例

编码器模式下,计数器的计数方向代表电机正反转,计数大小代表速度。

如下图所示,当电机正转时,编码器A通道(TI1)信号超前B通道,计数器向上计数。当电机反转时,A通道信号滞后并向下计数。

设置要反转的信号极性,使向下计数代表电机正转。

2 定时器编码器模式配置

以STM32芯片为例,其内部有专门用于采集增量编码器方波信号的接口。这些接口实际上是STM32定时器的功能之一。但编码器接口功能仅适用于高级定时器TIM1 和TIM8 以及通用定时器TIM2~TIM5。

正交编码器有两个正交输入信号(正交编码的介绍请参见之前的文章:编码器计数原理与电机测速原理——多图分析)。根据实际需要,可以设置只捕获某个通道的上升沿或下降沿,也可以设置同时捕获两个通道的上升沿和下降沿,从而保证该通道的计数精度。可以改进编码器,实现倍频。

编码器模式的配置实际上是通过配置SMCR寄存器和CCER寄存器来实现的。

2.1 SMCR寄存器配置触发模式

SMCR 是从机模式控制寄存器。查看STM32F4参考手册,可以找到类似下面的信息。现在我们只需要关注短信即可:

位15 ETP:外部触发极性

位14 ECE:外部时钟使能

Bit 13:12 ETPS:外部触发预分频器(External trigger prescaler)

Bit 11:8 ETF[3:0]:外部触发滤波器

Bit 7 MSM:主/从模式

位6:4 TS:触发选择

位3 保留,必须保存复位值

位2:0 SMS:从机模式选择

000:从模式禁用 如果CEN=“1”,则预分频器时钟直接由内部时钟提供。

001:编码器模式1 计数器根据TI1FP1 电平在TI2FP2 边沿向上/向下计数。

010:编码器模式2 计数器根据TI2FP2 电平在TI1FP1 边沿向上/向下计数。

011:编码器模式3——计数器在TI1FP1和TI2FP2的边沿计数,计数方向取决于另一个信号的电平。

100:复位模式——重新初始化计数器并在所选触发输入(TRGI) 的上升沿生成寄存器更新事件。

101:门控模式——当触发输入(TRGI)为高电平时启用计数器时钟。一旦触发输入变低,计数器立即停止计数(但不会重置)。计数器的启动和停止受到控制。

110:触发模式——当触发信号TRGI的上升沿出现时,计数器启动(但不复位)。仅控制计数器的启动。

111:外部时钟模式1 计数器时钟由所选触发信号(TRGI) 的上升沿提供。

上面对SMCR寄存器的介绍中,TI1、TI2等的功能:

TI1和TI2对应编码器的A、B两相输入信号。

TI1FP1和TI2FP2是TI1和TI2经过输入滤波和极性选择后的信号。如果不进行滤波和反转,则TI1FP1=TI1,TI2FP2=TI2。

从上面SMCR寄存器的功能介绍可知,选择编码器接口模式时:

如果计数器仅对TI2 边沿进行计数,则在TIMx_SMCR 寄存器中写入SMS=001

如果计数器仅对TI1 边沿进行计数,则写入SMS=010

如果计数器在TI1 和TI2 边沿计数,则写入SMS=011

定时器的编码器模式根据两个输入的信号转换序列生成计数脉冲和方向信号。根据信号转换顺序,计数器相应地向上或向下计数,硬件相应地修改TIMx_CR1寄存器的DIR位。当任何输入(TI1 或TI2)上发生信号转换时,都会计算DIR 位。

2.2 CCER寄存器配置极性

TI1 和TI2 极性可以通过编程TIMx_CCER 寄存器的CC1P 和CC2P 位来选择。其实就是设置TIxFP1是否与TIx取反来设置正转时是倒计数还是倒计数。

位15、11、7、3 CCxNP:捕捉/比较输出极性

位14、10、6、2 被保留,必须保存复位值

位13、9、5、1 CCxP:捕捉/比较输出极性。

00:同相/上升沿触发电路对TIxFP1 上升沿敏感(复位模式、外部时钟模式或触发模式下的捕获或触发操作),TIxFP1 不反相(门控模式或编码器模式下的触发操作)。

01:反相/下降沿触发电路对TIxFP1 下降沿(复位模式、外部时钟模式或触发模式下的捕获或触发操作)、TIxFP1 反相(门控模式或编码器模式下的触发操作)敏感。

10:保留,不要使用该配置。

11:同相/上升沿和下降沿触发电路对TIxFP1 的上升沿和下降沿敏感(在复位模式、外部时钟模式或触发模式下执行捕获或触发操作),TIxFP1 不反相(门控模式时) 。此配置不得在编码器模式下使用!

0:OCx高电平有效

1:OCx低电平有效

CCx 通道配置为输出:

CCx 通道配置为输入:

CCxNP/CCxP 位选择用于触发或捕捉操作的TI1FP1 和TI2FP1 的极性。

位12, 8, 4, 0 CCxE:捕捉/比较输出使能

注:编码器模式下,极性的作用是设置TIxFP1是否反转。不要被“上升沿灵敏度”误导,只捕获上升沿信号!

“上升沿敏感”是非编码器模式下的功能。因此,在编码模式下,只能配置为00或01。

另一方面,在编码器模式下,乘数只能通过SMCR 模式设置,可以是2 个乘数,也可以是4 个乘数。好像不能设置1倍频(仅针对一个通道的上升沿或下降沿)。边数)。

2.3 CCMR寄存器配滤波参数

如果需要,还可以通过配置CCMR寄存器的IC1F和IC2F来进行编码器输入信号的滤波配置:

这些寄存器的描述在前面的文章中已经介绍过,这里不再展开。

3 计数方向对照表解读

在编码器模式下,计数器的计数方向(向上或向下计数)会根据增量编码器的速度和方向自动修改,因此其计数值始终代表编码器的位置。计数方向对应于所连接传感器的旋转方向。下表总结了可能的组合(假设TI1 和TI2 不同时切换)。

注意:在计数时,STM32编码器接口并不是简单地采集某个通道信号的上升沿或下降沿,而是需要合成另一个通道信号的电平。 (通俗点讲,使用编码器接口时,需要将编码器的两个输入通道A、B进行电连接!虽然你只对一个通道设置了计数,但是该通道的计数时序需要参考信号)表中“对端信号电平”是指计数时参考的另一通道信号电平。这些电平决定了计数器的计数方向。

3.1 仅在TI1处计数

这里,仅在TI1计数意味着仅对编码器通道A的信号跳变进行计数。我们以电机正转为例:

注:以下介绍中,“通道A”代表TI1,“通道B”代表TI2。

3.1.1 电机正转(向上计数)

假设电机正转时,编码后的A通道信号比B通道提前1/4周期(即相位超前90度),并且A通道的上升沿和下降沿都被计数(如下图TI1波形)绿色和红色箭头),因为计数方向代表电机旋转方向,所以在正转的情况下:

A通道上升沿、B通道为低电平,向上计数,代表电机正转。

A通道下降沿,B通道高电平,向上计数,代表电机正转。

3.1.2 电机反转(向下计数)

反转情况下,编码后的通道A信号落后通道B 1/4周期:

A通道下降沿,B通道低电平,向上计数,代表电机反转

A通道上升沿,B通道为高电平,向上计数,代表电机反转

3.2 仅在TI2处计数

仅在TI2 计数意味着仅对编码器通道B 的信号跳变进行计数。又可分为正转和反转两种情况。具体对应关系请参考上文“仅在TI1时计数”。分析表明,通道A和通道B实际上在功能上是等效的。

3.3 在TI1与TI2处均计数

在TI1和TI2同时计数是指编码器A通道和B通道的信号同时被计数和计数。这样可以提高计数频率,实现倍频。

这里我们也以电机正转为例*:

观察下图,编码器一开始可以依次捕获:通道A的上升沿、通道B的上升沿、通道A的下降沿、通道B的下降沿,因此有:

A通道上升沿、B通道为低电平,向上计数,代表电机正转。

B通道上升沿,A通道为高电平,向上计数,表明电机正转。

A通道下降沿,B通道高电平,向上计数,代表电机正转。

B通道下降沿,A通道为高电平,向上计数,代表电机正转。

4 编程实现

4.1 定时器编码器模式配置

这里使用的通用定时器是TIM4。配置定时器最基本的功能就是配置时基。要使用输入功能,还需要配置定时器的GPIO和输入通道。

#define ENCODER_TIM_PSC 0 /*计数器分频*/#define ENCODER_TIM_PERIOD 65535 /*计数器最大值*/#define CNT_INIT 0 /*计数器初始值*/void TIM4_ENCODER_Init(void) {GPIO_InitTypeDef GPIO_InitStruct; /*GPIO*/TIM_TimeBaseInitTypeDef TIM _TimeBaseStruct; /*时基*/TIM_ICInitTypeDef TIM_ICInitStruct; /*输入通道*//*GPIO初始化*/RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); /*使能GPIO时钟AHB1*/GPIO_StructInit(GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin=GPIO_ Pin_6 | GPIO_Pin_7; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF; /*复用函数*/GPIO_InitStruct.GPIO_Speed=GPIO_Speed_100MHz; /*速度100MHz*/GPIO_InitStruct.GPIO_OType=GPIO_OType_PP; GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_NOPULL; GPIO_ Init(GPIOB, GPIO_InitStruct);GPIO_PinAFConfig(GPIOB,GPIO_PinSource6, GPIO_AF_TIM4);GPIO_PinAFConfig(GPIOB,GPIO_PinSource7,GPIO_AF_TIM4);/*时基初始化*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); /*使能定时器时钟APB1*/TIM_DeInit(TIM4); TIM_TimeBaseStructInit(TI M_TimeBaseStruct); TIM_TimeBaseStruct.TIM_Prescaler=ENCODER_TIM_PSC; /*预分频器*/TIM_TimeBaseStruct.TIM_Period=ENCODER_TIM_PERIOD; /*周期(重载值)*/TIM_TimeBaseStruct.TIM_ClockDivision=TIM_CKD_DIV1; TIM_TimeBaseStruct.TIM_CounterMode=TIM_CounterMode_Up; /*连续向上计数模式*/T IM_TimeBaseInit(TIM4, TIM_TimeBaseStruct );/*编码器模式配置:同时捕获通道1和通道2(即4倍频),极性为Rising*/TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12 ,TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);TIM_ICStructInit(TIM_ICInitStruct); TIM_ICInitStruct.TIM_ICFilter=0; /*输入通道的过滤参数*/TIM_ICInit(TIM4, TIM_ICInitStruct); /*输入通道初始化*/TIM_SetCounter(TIM4, CNT_INIT); /*CNT初始值*/TIM_ClearFlag(TIM4,TIM_IT_Update); /*中断清除标志位为0*/TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE); /*使能中断*/TIM_Cmd(TIM4,ENABLE); /*使能CR寄存器*/} 这里设置定时器的计数溢出值为65535,即TIM4的最大计数值(TIM4为16位计数器)。目的是避免计数器溢出,简化后续的速度计算方法(如果计数器溢出,计算速度时必须考虑溢出次数)。

编码器模式设置为TIM_EncoderMode_TI12,即对两个信号进行计数,实现4倍频率。

两个编码器输入的极性均设置为TIM_ICPolarity_Rising,即极性不反转。

这里,编码器模式设置调用TIM_EncoderInterfaceConfig()函数,该函数内部配置相关寄存器:

无效TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx,uint16_t TIM_EncoderMode,uint16_t TIM_IC1Polarity,uint16_t TIM_IC2Polarity){uint16_t tmpsmcr=0;uint16_t tmpccmr1=0;uint16_t tmpccer=0; /* 检查参数*/assert_param(IS_TIM_LIST2_PERIPH(TIMx));assert_param(IS_TIM_ENCODER_MODE (Tim_encodermode); Assert_param (IS_TIM_IC_POLIRITY (Tim_ic1极性));assert_param (IS_TIM_IC_POLALITY (Tim_ic2极性)); TMPSMCR=TI MX-SMCR;/*获取timx smcr寄存器值*/tmpccmr1=TIMX-CCMR1;/*获取timx ccmr1寄存器值*/tmpccer=TIMx-CCER;/*获取TIMx CCER寄存器值*/tmpsmcr=(uint16_t)~TIM_SMCR_SMS;/*设置编码器Mode */tmpsmcr |=TIM_EncoderMode;/* 选择捕捉比较1 和捕捉比较2 作为输入*/tmpccmr1=((uint16_t)~TIM_CCMR1_CC1S) ((uint16_t)~TIM_CCMR1_CC2S);tmpccmr1 |=TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0;/*设置TI1 和TI2 极性*/tmpccer=((uint16_t) ~TIM_CCER_CC1P) ((uint16_t)~TIM_CCER_CC2P);tmpccer |=(uint16_t)(TIM_IC1Polarity | (uint16_t)(TIM_IC2Polarity (uint16_t)4));TIMx-SMCR=tmpsmcr; /* 将配置数据写入SMCR 寄存器*/TIMx-CCMR1=tmpccmr1 ; /* 将配置数据写入CCMR1 寄存器*/TIMx-CCER=tmpccer; /* 将配置数据写入CCER寄存器*/}

4.2 电机转轴转速计算

这里使用直流减速电机:

减速比为34(即电机轴旋转1圈,电机本身旋转34圈)

电机一转的物理脉冲数为11

因此,电机轴旋转一圈,可产生的物理脉冲为34*11=374个。由于编码器模式实现了4倍频计数,因此电机轴旋转一圈,定时器可计数3744=1496。

对于速度的计算,这里采用的是M法测速(M法测速的具体原理可以参考之前的文章:http://www.elecfans.com/d/1639052.html),即计数固定时间间隔内编码器的脉冲数,计算出速度值。

,单位:转/秒

C:编码器单转的脉冲总数

每次统计时间(单位:秒)

:这段时间内计数的编码器脉冲数

例如,对于本实验中的电机,当轴旋转一圈时,定时器计数1496,即C=1496,对应程序中的TOTAL_RESOLUTION。 T0可以选择100ms,即0.1s。

程序编写如下。这里,另一个定时器7用于每100ms调用calc_motor_rotate_speed()函数来实时计算速度。每次使用read_encoder()读取编码器的值时,将计数值CNT设置为初始值0,并重新开始计数,这样每次读取都保证是前100ms的计数值。

另外,通过将CNT的uint32类型计数值转换为int16类型,可以用正负来区分电机在最后100ms内的整体旋转方向(正转CNT从0向上计数,仍然是正数)转为int16时的值;反转如果转换为CNT从0开始向下计数会溢出;如果转换为int16则为负数)。

#define ENCODER_RESOLUTION 11 /*编码器一转的物理脉冲数*/#define ENCODER_MULTIPLE 4 /*编码器倍频,由定时器的编码器模式设置*/#define MOTOR_REDUCTION_RATIO 34 /*电机减速比*//*电机一转的总脉冲数(定时器可读取的脉冲数)=编码器物理脉冲数*编码器倍频*电机减速比*/#define TOTAL_RESOLUTION (ENCODER_RESOLUTION* ENCODER_MULTIPLE*MOTOR_REDUCTION_RATIO)//读取定时器计数值static int read_encoder(void){int encoderNum=0;encoderNum=(int)((int16_t)(TIM4-CNT)); /*CNT为uint32,转换为int16*/TIM_SetCounter(TIM4, CNT_INIT); /*CNT设置初始值*/returnencoderNum;}//计算电机速度(由另一个定时器每100ms调用一次) void calc_motor_rotate_speed(){intencoderNum=0; floatrotateSpeed=0;/*读取编码器的值,正负代表旋转方向*/encoderNum=read_encoder();/*旋转速度(一秒转多少圈)=单位时间计数值/总计分辨率* 时间系数*/rotateSpeed=(float)encoderNum/TOTAL_RESOLUTION*10;printf('encoder: %d\t speed:%.2f rps\r\n',encoderNum,rotateSpeed);}

5 实验演示

通过发送指令串口控制另一个定时器产生指定占空比的PWM。控制电机匀速旋转,然后测试编码器读取的速度值。

(串口指令使用了字符串切割和串口接收变长字符的功能,请参考之前的文章:和部分内容,PWM的生成请参考:)

视频中,串口打印的编码器是100ms内读取到的编码器的计数值。正号和负号代表正转和反转。速度是根据编码器的计数值计算出的电机输出轴的旋转速度。单位是每秒转数。

第一个是全速正反转,速度接近每秒5转。

然后通过调节pwm,使电机轴转速接近每秒1转。由于理论上1转有1496个脉冲,每100ms读取一次,所以大约可以读取149个脉冲,与理论值相符。

视频演示:https://www.bilibili.com/video/BV13p4y1h7F9

最新资讯

推荐资讯