【STM32开发之寄存器版】(八)-定时器的编码器接口模式

一、前言

1.1 编码器接口原理

编码器模式主要用于检测旋转编码器的转动方向和转动速度。旋转编码器一般输出两路相位相差90度的脉冲信号(称为A相和B相),通过这两路信号,定时器可以判断编码器的旋转方向,并计数转动的脉冲数

1.2 本次DEMO目标

本次DEMO将使用STM32F103ZET6的PA6(TIM3_CH1)PA7(TIM3_CH2)的编码器模式,测量电机AB相编码器的正转、反转以及速度信息。并通过串口1打印在上位机XCOM上。

1.3 实验环境介绍

除了之前几篇文章一直使用到的正点原子STM32F103ZET6精英板,本文还是用到了MG513P30_12V直流减速电机。如下图所示:

MG513P30_12V型电机的参数如下表所示: 

额定电压(V)额定电流(A)堵转电流(A)减速后空载转速(rpm)减速后额定转速(rpm)额定扭矩(kg.cm)堵转扭矩(kg.cm)功率(W)
120.363.2366±26293±2114.54

本文使用的MG513P30_12V型电机自带霍尔编码器,其参数如下所示:

型号编码器线数类型供电范围
霍尔编码器13ppr磁感应3.3-5V

本次DEMO的硬件接线方式如下:

开发板带编码器的电机
5V5V
GNDGND
PA6A相
PA7B相

二、STM32处理AB相编码器原理

选择编码器接口模式的方法是:如果计数器只在TI2的边沿计数,则置TIMx_SMCR寄存器中的SMS=001;如果只在TI1边沿计数,则置SMS=010;如果计数器同时在TI1和TI2边沿计数,则置SMS=011。本文选择计数器同时在TI1和TI2边沿计数

通过设置TIMx_CCER寄存器中的CC1P和CC2P位,可以选择TI1和TI2极性;如果需要,还可以对输入滤波器编程。

两个输入TI1和TI2被用来作为增量编码器的接口。假定计数器已经启动(TIMx_CR1寄存器中的CEN=’1’),计数器由每次在TI1FP1或TI2FP2上的有效跳变驱动。TI1FP1和TI2FP2是TI1和TI2在通过输入滤波器和极性控制后的信号;如果没有滤波和变相,则TI1FP1=TI1,TI2FP2=TI2。根据两个输入信号的跳变顺序,产生了计数脉冲和方向信号。依据两个输入信号的跳变顺序,计数器向上或向下计数,同时硬件对TIMx_CR1寄存器的DIR位进行相应的设置。不管计数器是依靠TI1计数、依靠TI2计数或者同时依靠TI1和TI2计数。在任一输入端(TI1或者TI2)的跳变都会重新计算DIR位。本文将TIM3_CH1映射到TI1,将TIM3_CH2映射到TI2。

编码器接口模式基本上相当于使用了一个带有方向选择的外部时钟。这意味着计数器只在0到TIMx_ARR寄存器的自动装载值之间连续计数(根据方向,或是0到ARR计数,或是ARR到0计数)。所以在开始计数之前必须配置TIMx_ARR;同样,捕获器、比较器、预分频器、触发输出特性等仍工作如常。

在这个模式下,计数器依照增量编码器的速度和方向被自动的修改,因此计数器的内容始终指示着编码器的位置。计数方向与相连的传感器旋转的方向对应。下表列出了所有可能的组合,假设TI1和TI2不同时变换。 

由于本文选择在TI1和TI2上计数,故仅需关注上表的最后两行。下图是一个计数器操作的实例,显示了计数信号的产生和方向控制。它还显示了当选择了双边沿时,输入抖动是如何被抑制的;抖动可能会在传感器的位置靠近一个转换点时产生。在这个例子中,我们假定配置如下:
● CC1S=’01’ (TIMx_CCMR1寄存器,IC1FP1映射到TI1) 
● CC2S=’01’ (TIMx_CCMR2寄存器,IC2FP2映射到TI2) 
● CC1P=’0’ (TIMx_CCER寄存器,IC1FP1不反相,IC1FP1=TI1) 
● CC2P=’0’ (TIMx_CCER寄存器,IC2FP2不反相,IC2FP2=TI2) 
● SMS=’011’ (TIMx_SMCR寄存器,所有的输入均在上升沿和下降沿有效). 
● CEN=’1’ (TIMx_CR1寄存器,计数器使能)

 我们将以1-8时刻为例,结合之前的表格对编码器工作原理进行剖析:

时刻TI1和TI2动作计数器动作
1TI2低电平,TI1FP1上升向上计数
2TI1高电平,TI2FP2上升向上计数
3TI2高电平,TI1FP1下降向上计数
4TI1低电平,TI2FP2下降向上计数
5TI1低电平,TI2FP2上升向下计数
6TI2高电平,TI1FP1上升向下计数
7TI1高电平,TI2FP2下降向下计数
8TI2低电平,TI1FP1下降向下计数

三、时钟树分析

对于时钟树的分析与【STM32开发之寄存器版】(六)-通用定时器中断 相同,供给TIM3的时钟TIM3CLK=72MHz,具体的时钟树配置如下图所示:

四、寄存器介绍

为实现定时器的编码器接口模式,需要控制以下几组寄存器:

寄存器作用
RCC_APB1ENRAPB1外设时钟使能寄存器
RCC_APB2ENRAPB2外设时钟使能寄存器
GPIOx_CRL端口配置低寄存器
TIMx_ARR自动重装载寄存器
TIMx_PSC预分频器
TIMx_CCMR1捕获/比较模式寄存器1
TIMx_CCER捕获/比较使能寄存器
TIMx_SMCR从模式控制寄存器
TIMx_CNT计数器
TIMx_CR1控制寄存器1

下面将对这些寄存器进行一一介绍。

4.1 APB1/2 外设时钟使能寄存器

对该寄存器的描述详见【STM32开发之寄存器版】(二)-USART需要对RCC_APB1ENR的第1位置1,使能定时器3时钟;对RCC_APB2ENR的第2位置1,使能并口A时钟。

4.2 GPIOx_CRL 端口配置低寄存器

对该寄存器的描述详见【STM32开发之寄存器版】(一)-GPIO将PA6和PA7设置为浮空输入。

4.3 TIMx_ARR 自动重装载寄存器

对该寄存器的描述详见【STM32开发之寄存器版】(六)-通用定时器中断本文将其设为0XFFFF。

4.4 TIMx_PSC 预分频器

对该寄存器的描述详见【STM32开发之寄存器版】(六)-通用定时器中断本文将其设置为0,即不分频。

4.5 TIMx_CCMR1 捕获/比较模式寄存器1

《STM32中文参考手册》对TIMx_CCMR1寄存器的描述如下:

这里我们重点关注IC2F、CC2S、IC1F和CC1S。

IC1F和IC2F分别为输入捕获1和输入捕获2的滤波器,我们在这里设置为0110,即数字滤波器长度为6.

CC1S和CC2S为捕获/比较选择,我们将其设置为01,即CC1和CC2通道被配置为输入,IC1映射在TI1上,IC2映射在TI2上

4.6 TIMx_CCER 捕获/比较使能寄存器

《STM32中文参考手册》对TIMx_CCER寄存器的描述如下:

这里我们重点关注CC1P和CC2P,这两位设置为0,当我们将CC1和CC2通道配置为输入后,信号不反相。 

4.7 TIMx_SMCR 从模式控制寄存器

《STM32中文参考手册》对TIMx_SMCR寄存器的描述如下:

这里我们重点关注SMS从模式选择,我们将其设置为011,即编码器模式3,根据另一个信号的输入电平,计数器在TI1FP1和TI2FP2的边沿向上/下计数。

4.8 TIMx_CNT 计数器

《STM32中文参考手册》对TIMx_CNT寄存器的描述如下:

可以直接从CNT中读取编码器计数值, 也可以通过写的方式清除编码器计数值。

4.9 TIMx_CR1 控制寄存器1

对该寄存器的描述详见【STM32开发之寄存器版】(六)-通用定时器中断,第0位为计数器的使能位,该位必须置1,才能让定时器开始计数

五、程序设计

本DEMO中的程序主要分为TIM3编码器模式初始化、编码器速度读取以及轮询主函数。完整版代码见【STM32开发之寄存器版】(八-附)-定时器的编码器接口模式

5.1 TIM3编码器模式初始化

本部分代码在HARDWARE/encoder.c/TIM3_Encoder_Init();该函数的作用是按照第四部分的寄存器介绍,将TIM3初始化为编码器模式。具体代码如下所示:

void TIM3_Encoder_Init(void){
	
	RCC->APB1ENR|=1<<1; 	    //TIM3时钟使能
	RCC->APB2ENR|=1<<2;       //使能PORTA时钟
	
	GPIOA->CRL  &= 0X00FFFFFF;//清除PA7和PA6的控制位
	GPIOA->CRL  |= 0X44000000;//将PA7和PA6设置为浮空输入
	
	TIM3->ARR   =  0xFFFF;	  //设定计数器自动重装值 
	TIM3->PSC   =  0x0000;		//预分频器不分频
	
	TIM3->CR1   &= 0XFCFF;		//清除TIM3_CR1的[9:8]时钟分频因子
	TIM3->CR1   |= 0X0000;    //设置时钟分频因子为0,即定时器时钟tCK_INT(72MHz)与数字滤波器采样频率tDTS相等。
	
	TIM3->CCMR1 &= 0XFF0F;    //清除TIM3_CCMR1的[7:4]IC1F
	TIM3->CCMR1 |= 0X0060;    //设置采样频率为fDTS/4,N=6
	
	TIM3->CCMR1 &= 0X0FFF;    //清除TIM3_CCMR1的[15:12]IC2F
	TIM3->CCMR1 |= 0X6000;    //设置采样频率为fDTS/4,N=6
	
	TIM3->CCER  &= 0XFFDD;    //清除TIM3_CCER的[5]和[1];
	TIM3->CCER  |= 0X0000;    //将CC1和CC2通道设置为输入捕获,不反相。
	
	TIM3->SMCR  &= 0XFFF8;    //清除TIM3_SMCR的[2:0]SMS从模式选择位
	TIM3->SMCR  |= 0X0003;		//设置为编码器模式3 – 根据另一个信号的输入电平,计数器在TI1FP1和TI2FP2的边沿向上/下计数。
	
	TIM3->CCMR1 &= 0XFCFC;    //清除TIM3_CCMR1的[9:8]CC2S和[1:0]CC1S
	TIM3->CCMR1 |= 0X0101;    //在输入捕获模式下,CC2通道被配置为输入,IC2映射在TI2上;CC1通道被配置为输入,IC1映射在TI1上
	
	TIM3->CNT   =  0;         //TIM3计数器清零
	TIM3->CR1   |= 0x01;      //使能定时器3
	
}

5.2 编码器速度读取

本部分代码在HARDWARE/encoder.c/GetMotorPulse();该函数的作用是读取编码器数值,并对电机旋转方向进行判定,最后将编码器数值清零,具体代码如下所示:

void GetMotorPulse(void)
{
	decoderCNT = TIM3->CNT;   //获得编码器计数值
	
	if(decoderCNT > 0X7FFF){
		decoderCNT = decoderCNT-0XFFFF;  //电机反向判定,临界值0X7FFF;
	}
	
	TIM3->CNT = 0;            //计数器清零

}

5.3 轮询主函数 

本部分代码在USER/test.c;该函数的作用是读取并打印编码器速度,具体代码如下所示:

#include "sys.h"
#include "delay.h"
#include "usart.h" 
#include "encoder.h"

int main(void)
{					   	
	Stm32_Clock_Init(9);	//系统时钟设置
	uart_init(72,115200);	//串口初始化为115200
	delay_init(72);	   	 	//延时初始化 
  TIM3_Encoder_Init();  //初始化编码器
	
  while(1)
	{
		GetMotorPulse();
		printf("电机转速为:%d\r\n",decoderCNT);
		delay_ms(20);
	}
}

六、上机实验

6.1 编码器原信号测量

将示波器CH1(黄色线)接编码器A相,CH2(绿色线)接编码器B相,电机正转时,编码器信号值如下所示,A相领先于B相若干相位

 电机正转时,编码器信号值如下所示,B相领先于A相若干相位。

当电机速度加快时,信号频率会增大,单位时间内计数器中的值就会越大。 

6.2 电机转速测试 

对电机进行正转和反转,查看XCOM串口信息,可以看到电机转速值:

至此定时器3编码器模式测试成功! 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值