stm32f103单片机—编码器测速

本文详细介绍了如何使用STM32F103ZET6开发板配合MG513P3012V电机的霍尔编码器进行速度测量。讲解了单片机资源要求,包括STM32的编码器模式定时器选择,以及编码器模式的工作原理和计数方式。同时,阐述了减速比的概念,并提供了编码器与单片机的接线示例,以及相应的初始化代码。此外,还给出了从定时器计数值到转速的计算方法和代码实现,包括M法测速的计算公式。最后,展示了读取定时器计数值和计算电机转速的函数。

一、涉及资源

stm32f103ZET6开发板(非指定)
MG513P3012V型号电机(带霍尔编码器)(非指定)

二、涉及概念

1、单片机资源要求

此种测速方法要求单片机的定时器具有编码器模式,对于stm32f1系列,具备编码器模式的定时器有TIM1/2/3/4/5/8,定时器使用通道1、2来实现编码器功能,接线时注意把A/B相接到定时器通道1/2的引脚。

2、减速比

电机结构
在这里插入图片描述
减速结构
在这里插入图片描述
减速比为1:30通俗地讲就是当电机外伸轴转1圈时实际轴转30圈,外伸轴我们一般接上轮胎等实际作用物体,而实际轴是电机自身的转子,霍尔编码器的检测对象是实际轴

3、测速原理

霍尔编码器工作方式

霍尔编码器是一种通过磁电转换将输出轴上的机械几何位移量转换成脉冲或数字量的传感器。霍尔编码器是由霍尔码盘和霍尔元件组成。霍尔码盘是在一 定直径的圆板上等分地布置有不同的磁极。电机旋转一圈霍尔元件发出特定数目的脉冲信号。,用时间间隔内接收的总的脉冲数目除以转一圈发出的脉冲数目即可得到转轴转的圈数,再除以时间间隔就能得到转速。 为判断转向,一般输出两组存在一定相位差的方波信号。

定时器判断电机正反转的依据

定时器通道1、通道2接收A相和B相的脉冲信号,转一圈A相和B相发出的脉冲数目是一样的,但是发送有先后之分。
在这里插入图片描述

定时器针对正反转的两种计数方式

定时器在编码器模式下有两种计数方式,正转时是从重载值开始向下减数,反转时是从零开始向上加数(正反是相对而言的)。例如,如果我设定定时器的重载值为0x7fff,那么当定时器接收到10个正转的脉冲时,计数值变为0x7ff3,当定时器接收到的是反转的脉冲时,定时器的计数值变为0x000A。

定时器编码器模式1、2、3

TI1和TI2分别为定时器的通道1和通道2
在这里插入图片描述

在这里插入图片描述
编码器模式3即为四倍频模式,这个模式下对于A和B相发过来的一组脉冲会有四次计数(四个跳变沿),这样就能将检测精度提到四倍。

4、M法测速

在这里插入图片描述

三、编码器与单片机的接线

注:这里以stm32f1系列的定时器4为例,若使用其他定时器进行测速需要更换对应的引脚资源,编码器A/B相需接到定时器的通道1和通道2

1、霍尔编码器实物图

在这里插入图片描述

接线

编码器A相和B相接PB6和PB7引脚(无对应要求)

四、单片机引脚和定时器的初始化

1、代码示例

引脚选择PB6和PB7
定时器选择TIM4,使用编码器模式3

/*****************************************************
*@Func:	编码器涉及资源的初始化
******
*@para:	
******
*@desc:	选择TIM4作为此编码器的解码时钟
******	设置重装值
******  注意:实际使用时对转速有限制,如果转速太快可能发生定时器溢出的情况,就要考虑使用中断
******  目前对脉冲一次定时仅能计32768次,超过即无效,可以分别正反转。
******	定时器在编码器模式下电机如果正转计数器会从零开始正数,如果反转计数器会从重载值开始倒数
******************************************************/ 
void EncoderA_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure; 			//	引脚初始化的结构体  
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;	//	定时器初始化的结构体
	TIM_ICInitTypeDef TIM_ICInitStructure; 			//	定时器编码器模式初始化的结构体
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); 	//	使能TIM4时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); 	//	使能GPIOB时钟
 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;	//	PB6、PB7
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 	//	浮空输入
	GPIO_Init(GPIOB, &GPIO_InitStructure);					//	根据GPIO_InitStructure的参数初始化GPIOB0

	TIM_TimeBaseStructure.TIM_Period = 0xffff; 				//	设定计数器自动重装值
	TIM_TimeBaseStructure.TIM_Prescaler = 0; 						//	预分频器 
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; 		//	选择时钟分频:不分频
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 	//	TIM向上计数模式
	TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); 				//	根据TIM_TimeBaseInitStruct的参数初始化定时器TIM4
	
	TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3:CH1、CH2同时计数,四分频
	
	//初始化TIM4输入捕获参数
	TIM_ICStructInit(&TIM_ICInitStructure); 							//	把TIM_ICInitStruct 中的每一个参数按缺省值填入
	TIM_ICInitStructure.TIM_ICFilter = 0x03;  							// 	IC1F=0011 配置输入滤波器(连续采样八次)
	TIM_ICInit(TIM4, &TIM_ICInitStructure); 							//	根TIM_ICInitStructure参数初始化定时器TIM4编码器模式

	TIM_Cmd(TIM4, ENABLE); 												// 使能定时器4
}

五、读定时器的计数值

定时器的计数值即为编码器发出的脉冲数目*4(定时器的编码器模式3)

/*****************************************************
*@Func:	读取定时器计数值
******
*@para:	
******
*@desc:	
******************************************************/ 
void Read_EncoderA(void)
{
	if(TIM4->CNT > 0x7fff)
	{
		EncoderA = TIM4->CNT - 0xffff;	// 反转
	}
	else
	{
		EncoderA = TIM4->CNT;			// 正转
	}
	TIM4->CNT = 0xffff;
}

六、由定时器计数值得到转速

1、计算公式

使用M法测速,计算公式为:
转速n = 总脉冲数/四倍频/单圈脉冲数/减速比/时间间隔

2、代码示例

电机转一圈本款霍尔编码器发出13个脉冲,本款电机的减速比为1:30

/*****************************************************
*@Func:	获取电机A的速度
******
*@para:	
******
*@desc:	返回的是电机的转速 n圈/s
******	转速n = 总脉冲数/四倍频/单圈脉冲数/减速比/时间		
******************************************************/ 
void Get_MotorA_Speed(void)
{
	Read_EncoderA();	// 获取编码器产生的脉冲数
	MotorASpeed = (float)EncoderA / 4 / PulseNum / ReRate / DecodeGapTime * 1000;
}
<think>好的,我现在需要回答用户关于编码器测速实现方法或编程示例的问题。用户提到了几个引用资料,涉及不同单片机(如51单片机STM32F103C8T6)的应用案例。首先,我需要整理编码器测速的基本原理和常见方法,然后结合引用中的具体实现步骤,给出编程示例。 首先,编码器测速通常有两种方法:M法(频率测量法)和T法(周期测量法)。M法通过测量单位时间内的脉冲数来计算转速,适用于高速;T法通过测量脉冲间隔时间来计算,适用于低速。用户提供的引用中提到了使用定时器捕获脉冲或使用编码器模式,这对应到不同的测速方法。 接下来,需要结合引用中的具体内容。引用[1]和[2]提到了使用51单片机,而引用[3]是关于STM32的,使用定时器的编码器模式。因此,我应该分别说明这两种不同的实现方式,并给出对应的代码示例。 对于51单片机,可能需要使用外部中断或定时器来计数脉冲。例如,配置定时器为计数器模式,或者用外部中断触发脉冲计数,然后在固定时间间隔内读取计数值,应用M法计算转速。代码部分需要展示如何初始化定时器/中断,以及计算速度的公式。 对于STM32,由于其高级定时器支持编码器模式,可以直接读取编码器的计数值。需要配置定时器的编码器接口,捕获A、B相的脉冲,然后通过定时器中断或主循环定期读取计数值,同样使用M法或T法计算转速。引用[3]提到使用PID控制,这可能是在测速后的闭环控制部分,但用户的问题主要关注测速,所以可能需要简化这部分。 此外,需要注意代码的注释和关键步骤的解释,确保用户能理解每部分的作用。同时,根据用户提供的引用,要正确引用来源,比如在提到51单片机时引用[2],STM32时引用[3]。 最后,生成相关问题,需要围绕编码器测速的不同方面,如方法比较、提高精度、低速处理、代码优化等,确保问题相关且有深度。</think>### 编码器测速的实现方法 #### 一、基本原理 编码器测速的核心是通过测量脉冲信号的数量或频率来推算转速。常见的测速方法包括: 1. **M法(频率测量法)**:在固定时间间隔内统计脉冲数,适用于高速场景,公式为: $$n = \frac{N}{T \cdot P}$$ 其中$n$为转速(转/秒),$N$为脉冲数,$T$为时间间隔,$P$为编码器每转一圈的脉冲数[^2]。 2. **T法(周期测量法)**:测量相邻脉冲的时间间隔,适用于低速场景,公式为: $$n = \frac{1}{T \cdot P}$$ 其中$T$为脉冲周期[^3]。 --- #### 二、技术实现步骤(以51单片机STM32为例) ##### 1. **基于51单片机的实现** **硬件配置**: - 编码器输出A、B两相脉冲信号,连接单片机外部中断引脚(如INT0、INT1)。 - 使用定时器计时固定间隔(如100ms)。 **编程步骤**: ```c #include <reg51.h> unsigned int pulse_count = 0; unsigned int speed_rpm = 0; // 外部中断0服务函数(脉冲计数) void EX0_ISR() interrupt 0 { pulse_count++; } // 定时器0初始化(定时100ms) void Timer0_Init() { TMOD |= 0x01; // 模式1(16位定时器) TH0 = 0x3C; // 初始值(50ms) TL0 = 0xB0; ET0 = 1; // 允许定时器0中断 TR0 = 1; // 启动定时器 } // 定时器0中断服务函数 void Timer0_ISR() interrupt 1 { TH0 = 0x3C; // 重新加载初值 TL0 = 0xB0; speed_rpm = (pulse_count * 60) / (0.1 * 500); // 假设编码器500脉冲/转 pulse_count = 0; } void main() { EA = 1; // 全局中断使能 EX0 = 1; // 允许外部中断0 Timer0_Init(); while(1); } ``` ##### 2. **基于STM32编码器模式** **硬件配置**: - 使用定时器的编码器接口模式(如TIM2),直接读取编码器计数值。 - 编码器A、B相分别接TIM2_CH1和TIM2_CH2。 **关键代码**: ```c // 初始化定时器为编码器模式 void Encoder_Init(TIM_TypeDef* TIMx) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct; TIM_ICInitTypeDef TIM_ICStruct; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); TIM_TimeBaseStruct.TIM_Prescaler = 0; TIM_TimeBaseStruct.TIM_Period = 0xFFFF; // 16位计数器最大值 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStruct); TIM_ICStruct.TIM_Channel = TIM_Channel_1; TIM_ICStruct.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICStruct.TIM_ICFilter = 0x0; TIM_ICInit(TIM2, &TIM_ICStruct); TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising); TIM_Cmd(TIM2, ENABLE); } // 读取速度(单位:转/分钟) int Get_Speed() { static int last_count = 0; int current_count = TIM_GetCounter(TIM2); int delta = current_count - last_count; last_count = current_count; return (delta * 60) / (0.1 * 500); // 假设采样间隔0.1秒,500脉冲/转 } ``` --- #### 三、关键注意事项 1. **消抖处理**:编码器信号需硬件滤波或软件去抖动。 2. **方向判断**:通过A、B相信号的相位差判断旋转方向[^3]。 3. **中断优先级**:STM32中需配置定时器中断优先级以避免冲突。 ---
评论 10
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值