实验目的:刚开始接触关机电机检测领域,准备探索关于定时器编码器的应用,用来检测脉冲数,从而进行转速的检测。
使用芯片:STM32F407
使用平台:STM32Cube IDE
1、使用编码器的原理
网上介绍如下:(以下介绍为复制内容)
编码器分为光电和霍尔编码器是一种将角位移或者角速度转换成一连串电数字脉冲的旋转式传感器,我们可以通过编码器测量到位移或者速度信息。
编码器从输出数据类型上分,可以分为增量式编码器和绝对式编码器。
从编码器检测原理上来分,还可以分为光学式、磁式、感应式、电容式。常见的是光电编码器(光学式)和霍尔编码器(磁式)。两种:
光电编码器是一种通过光电转换将输出轴上的机械几何位移量转换成脉冲或数字量的传感器。
光电编码器是由光码盘和光电检测装置组成。光码盘是在一 定直径的圆板上等分地开通若干个长方形孔。由于光电码盘与电动机同轴,电动机旋转时,检测装置检测输出若干脉冲信号,为判断转向,一般输出两组存在一 定相位差的方波信号。
因此,注意两个问题:一个是存在相位差的信号,二是两组方波信号
2、定时器配置
注:**这种测速的情况必须开启另一个定时器,用来表示在多少时间内测得的脉冲数。*例如目前使用TIM1,设为1s进行计数。
STM32Cube MX中进行定时器配置:定时器时钟频率为80MHz。
![]()
tips:定时器的说明:Prescaler为定时器的预分频系数,Period为定时器的自动重装值。如图所设,由于我们的使用Internal Clock也就是80MHz,根据所设值,80000000/(7999+1)=10000Hz,也就是100us,而自动重装值是9999,也就是100us(9999+1) = 1s,假设定时器开启中断后,每1s就会产生一次中断,也就是每1s计数器都会变成自动重装值,这就是定时1s。
3、定时器编码器模式设置
使用TIM3设为编码器模式,可以对两路有相位差(90°或者270°)的方波信号进行脉冲计数和方向位测试。
STM32Cube MX中进行定时器配置,用计数器的方式去理解
编码器的设置说明:首先我们需要将TIM3设为Encoder Mode模式。预分频系数为0,自动重载值为65535,由于是16位定时器就设为最大值0xFFFF。由于该定时器的模式,我们会用外部输入的脉冲作为时钟信号,因此Clock Source都是灰色无法选择的。而根据定时器所设参数,对于外部输入脉冲我们不分频,直接检测脉冲数,每65535个后如果设有中断就会触发一次溢出中断。
对于编码器模式:Encoder Mode可以有3种模式:Encode Mode TI1,Encode Mode TI2和Encode Mode TI1 and TI2。
这3中的设置区别就是触发源的选择上,分别对应为TIM3_CH1通道的上升沿或下降沿触发,TIM3_CH2通道的上升沿或下降沿触发,TIM3_CH1和TIM3_CH2所有的上升沿或下降沿触发。
而需要注意的是:对于Rising Edge和Falling Edge可以按我图上设也可以都设为Rising Edge,对于Encode Mode TI1 and TI2,无论设为Rising Edge还是Falling Edge,它都会在两路脉冲的上升沿和下降沿都进行计数。这也是网上常说4倍频的原因所在。
为大家理解,进行进一步说明:理解的可以直接跳到第4部分。
EncoderMode_TI1: Counter counts on TI1FP1 edge depending on TI2FP2 level,意思就是当选择模式1时,计数器根据TI2的电平高低来记录TI1的边沿信号。
假设A、B两相信号通过TI1、TI2输入到TIM3。
若我们选择的是模式1,即计数器仅在TI1的边沿处计数。我们观察TI1的上升沿,若此时对应的TI2信号处于低电平(下图红框),于是根据表格我们可以得到计数方向为递增,假设计数器递增时电机正向转动,则可判断此时电机正转。再观察下降沿,若此时对应的TI2信号处于高电平,那计数方向会递增,这就是模式1和2,会出现2倍频的情况,模式2与模式1类似,不再赘述。
Encode Mode TI1 and TI2:counts up/down on both TI1FP1 and TI2FP2 edges depending on the level of the other input.该模式下TI1和TI2的上升沿和下降沿都会进行计数,这就是四倍频。
4、程序实现
在主循环开始前
HAL_TIM_Encoder_Start_IT(&htim3,TIM_CHANNEL_ALL);//打开编码器中断
HAL_TIM_Base_Start_IT(&htim1);//开启1S定时中断
__HAL_TIM_ENABLE_IT(&htim3,TIM_IT_UPDATE);//更新中断用于溢出计数
在中断中
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//捕获中断中可以添加自己所需要的标志位
{
if(htim3.Instance->CR1 == 0x01)//顺时针
{}
if(htim3.Instance->CR1 == 0x11)//逆时针
{}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(TIM1 == htim->Instance)
{
t200 = 1;
}
if(TIM3 == htim->Instance)
{
TIM3UP++;
__HAL_TIM_CLEAR_IT(&htim3,TIM_IT_UPDATE);
if(htim3.Instance->CR1 == 0x01)//顺时针
{
circle_count++;
}
if(htim3.Instance->CR1 == 0x11)//逆时针
{
circle_count–;
}
}
1
}
在主循环中
if(t200 == 1)
{
t200 = 0;
HAL_TIM_Encoder_Stop(&htim3,TIM_CHANNEL_ALL);
__HAL_TIM_DISABLE_IT(&htim3,TIM_IT_UPDATE);
directuinA = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim3);//用来获取方向
if(directuinA == 0)//顺时针,会从0开始向上计数,来一个脉冲,增加一个计数
{
CaptureNumberA = TIM3UP * 65535 + __HAL_TIM_GET_COUNTER(&htim3);
}
else if(directuinA == 1)//逆时针,会从65535开始向下计数,来一个脉冲,减去一个计数;TIM3UP 是为了计数溢出所添加的
{
CaptureNumberA = TIM3UP * 65535 - __HAL_TIM_GET_COUNTER(&htim3) + 1;
}
//除以4是由于四倍频的缘故,PULSE_CIRCLE是指一圈有多少脉冲,*60是为了换算成r/min
T_SPEED = (CaptureNumberA / 4.0) / PULSE_CIRCLE * 60;
HAL_TIM_Base_Stop(&htim3);
__HAL_TIM_SET_COUNTER(&htim3,0);
TIM3UP = 0;
HAL_TIM_Base_Start(&htim3);
}
5、实验结果
设PULSE_CIRCLE = 1也就是一圈一个脉冲,两路输入频率均为1000HZ,相位90°,定时1S,1S内的directuinA = 0,表示顺时针,CaptureNumberA = 4000表示脉冲个数,T_SPEED表示所转圈数
相位270°,定时1S,1S内的directuinA = 1,表示逆时针,CaptureNumberA = 3999表示脉冲个数,T_SPEED表示所转圈数
能力有限,不足之处还需指出,期待大家的交流,码字不易,且读且珍惜!