STM32——编码器测速原理及STM32编码器模式
1. 编码器概述
编码器是一种将角位移或者角速度转换成一连串电数字脉冲的旋转式传感 器,我们可以通过编码器测量到底位移或者速度信息。编码器从输出数据类型上 分,可以分为增量式编码器和绝对式编码器。
从编码器检测原理上来分,还可以分为光学式、磁式、感应式、电容式。常 见的是光电编码器(光学式)和霍尔编码器(磁式)。
2. 编码器原理
光电编码器是一种通过光电转换将输出轴上的机械几何位移量转换成脉冲或数字量的传感器。光电编码器是由光码盘和光电检测装置组成。光码盘是在一 定直径的圆板上等分地开通若干个长方形孔。由于光电码盘与电动机同轴,电动机旋转时,检测装置检测输出若干脉冲信号,为判断转向,一般输出两组存在一 定相位差的方波信号。
霍尔编码器是一种通过磁电转换将输出轴上的机械几何位移量转换成脉冲或数字量的传感器。霍尔编码器是由霍尔码盘和霍尔元件组成。霍尔码盘是在一 定直径的圆板上等分地布置有不同的磁极。霍尔码盘与电动机同轴,电动机旋转时,霍尔元件检测输出若干脉冲信号,为判断转向,一般输出两组存在一定相位差的方波信号。
可以看到两种原理的编码器目的都是获取 AB 相输出的方波信号,其使用方法也是一样,下面是一个简单的示意图。
3. 编码器接线说明
具体到我们的编码器电机,我们可以看看电机编码器的实物。
4. 编码器软件四倍频技术
下面我们说一下编码器倍频的原理。为了提高大家下面学习的兴趣,我们先明确,这是一项实用的技术,可以真正地把编码器的精度提升 4 倍。作用可类比 于单反相机的光学变焦,而并非牺牲清晰度来放大图像的数码变焦。OK,先看看下面编码器输出的波形图。
这里,我们是通过软件的方法实现四倍频。首先可以看到上图编码器输出的AB 相波形,正常情况下我们使用 M 法测速的时候,会通过测量单位时间内 A 相输出的脉冲数来得到速度信息。常规的方法,我们只测量 A 相(或 B 相)的上升 沿或者下降沿,也就是上图中对应的数字 1234 中的某一个,这样就只能计数 3次。而四倍频的方法是测量 A 相和 B 相编码器的上升沿和下降沿。这样在同样的 时间内,可以计数 12 次(3 个 1234 的循环)。这就是软件四倍频的原理。
5. STM32编码器模式
在STM32中,编码器使用的是定时器接口,通过数据手册可知,定时器1,2,3,4,5和8有编码器的功能,而其他没有。编码器输入信号TI1,TI2经过输入滤波,边沿检测产生TI1FP1,TI2FP2接到编码器模块,通过配置编码器的工作模式,即可以对编码器进行正向/反向计数。
STM32编码器有三种工作模式,其中模式三即为上文中提到的四倍频模式。
在使用编码器模式时需要注意以下几点:
- 编码器有个转速上限,超过这个上限是不能正常工作的,这个是硬件的限制,原则上线数越多转速就越低,这点在选型时要注意。
- 定时器初始化好以后,任何时候CNT寄存器的值就是编码器的位置信息,正转他会加反转他会减这部分是不需要软件干预的,初始化时给的TIM_Period 值应该是码盘整圈的刻度值,在减溢出会自动修正为这个数.加超过此数值就回0.
- 计数值偶尔也会有出错误的情况,一圈多计一个或少计一个数都是很正常的特别是转速比较高的时候尤其明显,有个绝对位置信号做修正是很有必要的.绝对位置信号不需要一定在零位置点,收到这个信号就将CNT修正为一个固定的数值即可.
6. STM32编码器模式例程
此例程用于初始化定时器2和定时器3为编码器模式,得到小车底盘上两个直流电机的运转速度。
#.c文件
#include "encoder.h"/**************************************************************************
* 函数功能:把TIM2初始化为编码器接口模式
*
* 入口参数:无
*
* 返 回 值:无
**************************************************************************/
void Encoder_Init_TIM2(void)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_ICInitTypeDef TIM_ICInitStructure; GPIO_InitTypeDef GPIO_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能定时器2的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);//使能PA PB端口时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; //端口配置 PA15GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOAGPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //端口配置 PB3GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOBTIM_TimeBaseStructInit(&TIM_TimeBaseStructure);TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 预分频器 TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD; //设定计数器自动重装值TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//边沿计数模式 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //初始化定时器2TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3TIM_ICStructInit(&TIM_ICInitStructure); //把TIM_ICInitStruct 中的每一个参数按缺省值填入TIM_ICInitStructure.TIM_ICFilter = 10; //设置滤波器长度TIM_ICInit(TIM2, &TIM_ICInitStructure);//根据 TIM_ICInitStruct 的参数初始化外设 TIMxTIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除TIM的更新标志位TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//使能定时器中断TIM_SetCounter(TIM2,0);TIM_Cmd(TIM2, ENABLE); //使能定时器2
}/**************************************************************************
函数功能:把TIM3初始化为编码器接口模式
入口参数:无
返回 值:无
**************************************************************************/
void Encoder_Init_TIM3(void)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_ICInitTypeDef TIM_ICInitStructure; GPIO_InitTypeDef GPIO_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//使能定时器3的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PA端口时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //端口配置 PA6 PA7GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOATIM_TimeBaseStructInit(&TIM_TimeBaseStructure);TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 预分频器 TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD; //设定计数器自动重装值TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//边沿计数模式 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //初始化定时器3TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12,TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3(TIM_ICPolarity_Rising或者TIM_ICPolarity_Falling效果相同,都是4倍频)TIM_ICStructInit(&TIM_ICInitStructure); //把TIM_ICInitStruct 中的每一个参数按缺省值填入TIM_ICInitStructure.TIM_ICFilter = 10; //设置滤波器长度TIM_ICInit(TIM3, &TIM_ICInitStructure);//根据 TIM_ICInitStruct 的参数初始化外设 TIMxTIM_ClearFlag(TIM3, TIM_FLAG_Update);//清除TIM的更新标志位TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);//使能定时器中断TIM_SetCounter(TIM3,0);TIM_Cmd(TIM3, ENABLE); //使能定时器
}/**************************************************************************
函数功能:单位时间读取编码器A计数
入口参数:无
返回 值:计数值
**************************************************************************/
float Read_EncoderA(void)
{int Encoder_TIM = 0; float Speed = 0.0; Encoder_TIM= (short)TIM2 -> CNT; TIM2 -> CNT=0;return -Encoder_TIM;
}
/**************************************************************************
函数功能:单位时间读取编码器B计数
入口参数:无
返回 值:计数值
**************************************************************************/
float Read_EncoderB(void)
{int Encoder_TIM = 0; float Speed = 0.0; Encoder_TIM= (short)TIM3 -> CNT; TIM3 -> CNT=0;return Encoder_TIM;
}/**************************************************************************
* 函数功能:TIM2中断服务函数
*
* 入口参数:无
*
* 返 回 值:无
**************************************************************************/
void TIM2_IRQHandler(void)
{ if(TIM2->SR&0X0001)//溢出中断{ } TIM2->SR&=~(1<<0);//清除中断标志位
}/**************************************************************************
* 函数功能:TIM3中断服务函数
*
* 入口参数:无
*
* 返 回 值:无
**************************************************************************/
void TIM3_IRQHandler(void)
{ if(TIM3->SR&0X0001)//溢出中断{ } TIM3->SR&=~(1<<0);//清除中断标志位
}
#.h文件
#define __ENCODER_H
#include <sys.h>
#include "init.h" //include了所有需要的头文件
#define ENCODER_TIM_PERIOD (u16)(65535) //不可大于65535 因为F103的定时器是16位的。void Encoder_Init_TIM2(void);
void Encoder_Init_TIM3(void);float Read_EncoderA(void);
float Read_EncoderB(void);void TIM2_IRQHandler(void);
void TIM3_IRQHandler(void);#endif
STM32——编码器测速原理及STM32编码器模式相关推荐
- 编码器测速原理与实现
目录: 一.测速原理 二.CubeMX配置编码器模式 三.利用外部中断采集脉冲 一.测速原理 通常情况下编码器旋转一周会输出固定的脉冲数,即编码器的分辨率,通过测量固定时间T内编码器输出的脉冲数即可求 ...
- STM32应用(九)编码器及其测速原理、L298N电机驱动控制编码器电机
文章目录 1.L298N电机驱动 1.1 产品参数 1.2 实物图和接线 2.编码器 2.1 编码器简介 2.2 常用编码器分类 2.3 霍尔编码器实物图接线!!!! 2.4 编码器倍频原理 3.控制 ...
- 平衡小车—编码器使用教程与测速原理
文章目录 1.编码器概述 2.编码器原理 3.编码器接线说明 4.编码器软件四倍频技术 5.单片机如何采集编码器数据 6.获取方式 来自平衡小车之家,与大家一起学习编码器使用与测速原理. 1.编码器概 ...
- 【一文读懂】如何用编码器测速
文章目录 前言 一.AB相编码器计数原理 四倍频 二.要用到的一些参数 编码器参数 电机参数 轮子参数 计算 三.代码如下(更契合原理的代码) 四倍频的代码(更新) 前言 详解编码器测速原理及实现 参 ...
- 直流有刷电机编码器测速基于STM32F302R8+X-NUCLEO-IHM07M1
文章目录 前言 一.编码器测速原理 二.STM32F302R8+X-NUCLEO-IHM07M1直流电机编码器测速 2.1.功能需求 2.2.硬件设计 2.3.软件设计 2.3.1.底层配置 2.3. ...
- STM32 CubeMax 编码器电机测速 原理与实现
编码器电机测速 部分参考:https://blog.csdn.net/lzzzzzzm/article/details/119416134 其他参考部分见图片水印 1. 编码器种类及原理 常见的编码器 ...
- STM32单片机—编码器测速
一.实验工具:STM32开发板一块.L298N电机驱动.直流电机 以及用到的软件(STM32CubeMX.keil4) 二.编码器原理 1.概述:编码器是一种将角位移或者角速度转换成一串电数字脉冲的旋 ...
- STM32 HAL库实现编码器测速
STM32 HAL库实现编码器测速 (还开了串口1用来调试,下文没写:然后那个short的用法就是看平衡小车之家(就是喵呜实验室的文档里头的,用法确实惊艳),文末贴了工程) 编码器接口模式 TI1和T ...
- stm32霍尔编码器测速(标准库函数版)
基本原理:霍尔编码器是有霍尔马盘和霍尔元件组成.霍尔马盘是在一定直径的圆板上等分的布置有不同的磁极.霍尔马盘与电动机同轴,电动机旋转时,霍尔元件检测输出若干脉冲信号,为判断转向,一般输出两组存在一定相 ...
最新文章
- 【译】GraphQL vs. REST
- 崩溃!双十一第 4 天,某互联网公司黄了?
- mysql istransient_由于 MySQL 版本问题导入报错
- 【链表】BZOJ1588: [HNOI2002]营业额统计
- 一个基于Mule的企业服务总线的案例(关于JMS)
- 监控工具—Prometheus—基础介绍
- Sicily 1346. 金明的预算方案
- 算法积累之处理数组数据
- 2d绘制 c# dx_C# 从零开始写 SharpDx 应用 绘制基础图形
- python3 copy_Python3 深浅拷贝
- 减少 JavaScript 代码量的原生技术
- 20个问题:平凡的天才人格特质
- rac备份及恢复的重要概念之一——Redo Threads和Streams
- 编译原理完整学习笔记(七):优化代码
- scratch好书推荐
- Help Hanzo LightOJ - 1197(素数筛法)
- python itchat实现调用微信接口的第三方模块方法
- 镂空三角形(for循环找规律)
- 运动的“点”与“线”,竟然能产生错觉???
- 《痞子衡嵌入式半月刊》 第 68 期