编码器如何在stm32上使用?

编码器如何在stm32上使用

1. 编码器是什么?

编码器是一种传感器或设备,用于测量位置、角度或速度,并将这些物理量转换成电信号,通常是数字信号。它们广泛应用于工业自动化、机器人技术、航空航天、汽车和其他需要精确控制和反馈的系统中。

根据其工作原理和应用的不同,编码器可以分为以下几种主要类型:

  1. 增量式编码器

    • 每次转动时输出脉冲信号,通过计数这些脉冲来确定轴的位置变化。
    • 通常包含A相和B相输出,用于指示方向;有些还可能有Z相输出,用于提供每转一圈的参考点。
    • 常用于需要连续监控运动的应用中。
  2. 绝对式编码器

    • 提供轴的即时位置信息,即使在断电后重新上电也能立即知道当前位置。
    • 使用多种技术(如磁性、光学等)来存储位置信息,因此不需要外部电源就能记住位置。
    • 适用于需要高精度定位且不希望每次启动都需要校准的应用。
  3. 旋变式编码器

    • 利用变压器原理来检测旋转角度。
    • 输出模拟电压信号,与转子的角度成正比。
    • 在某些需要高可靠性的应用中使用,例如飞机和重型机械。
  4. 混合型编码器

    • 结合了增量式和绝对式的功能,可以在提供增量反馈的同时记录绝对位置。

2. 如何在stm32上使用编码器

使用编码器的主要原理是将物理位移或者旋转转化为可被电子系统识别的电信号。增量式编码器是最常用的类型之一。

1. 编码器的基本原理

  1. 基本组成:

    • A相: 代表编码器的主脉冲。
    • B相: 与A相相位相差90度,用于确定旋转的方向。
    • Z相(可选): 提供每转一圈的参考点。
  2. 工作方式:

    • 当编码器轴旋转时,A相和B相产生一系列脉冲信号。
    • A相和B相的脉冲序列可以用来计算轴的位置变化。
    • A相领先B相90度表示顺时针旋转,而B相领先A相90度则表示逆时针旋转。
  3. 脉冲计数:

    • 通过计数A相的上升沿或下降沿来确定位置变化。
    • 根据A相和B相的相对顺序判断旋转方向。
      在这里插入图片描述

2. STM32上的实现

在STM32上使用编码器通常涉及到以下几个步骤:

  1. 配置GPIO:
    • 选择合适的GPIO引脚作为编码器的输入。
    • 配置这些引脚为输入模式,并设置适当的上拉或下拉电阻。
  2. 配置定时器:
    • 选择支持编码器模式的定时器,如TIM1、TIM2、TIM3等。
    • 设置定时器的工作模式为编码器模式。
    • 配置捕获比较通道以匹配A相和B相输入。
  3. 中断配置:
    • 使能定时器的中断,以便在检测到A相或B相的变化时触发中断。
    • 在中断服务程序中更新计数器,根据A相和B相的状态确定旋转方向。
  4. 软件处理:
    • 在中断服务程序中处理计数逻辑,比如增加或减少计数值。

3. 代码实现

#include "stm32f10x.h"                  // Device header

void Encoder_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
		
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;		//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;		//PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
	
	TIM_ICInitTypeDef TIM_ICInitStructure;
	TIM_ICStructInit(&TIM_ICInitStructure);
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
	TIM_ICInitStructure.TIM_ICFilter = 0xF;
	TIM_ICInit(TIM3, &TIM_ICInitStructure);
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
	TIM_ICInitStructure.TIM_ICFilter = 0xF;
	TIM_ICInit(TIM3, &TIM_ICInitStructure);
	
	TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
	
	TIM_Cmd(TIM3, ENABLE);
}

int16_t Encoder_Get(void)
{
	int16_t Temp;
	Temp = TIM_GetCounter(TIM3);
	TIM_SetCounter(TIM3, 0);
	return Temp;
}

原理

#include "stm32f10x.h"                  // Device header
  • 包含STM32F1系列微控制器的标准外设库头文件。
void Encoder_Init(void)
{
  • 定义初始化编码器接口的函数 Encoder_Init
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  • 使能TIM3定时器时钟。
  • 使能GPIOA时钟,因为编码器的输入引脚连接到了GPIOA。
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
  • 定义一个GPIO初始化结构体 GPIO_InitStructure
  • 设置GPIOA的第6和第7引脚为上拉输入模式。
  • 设置这两个引脚的最大速度为50MHz。
  • 调用 GPIO_Init 函数初始化GPIOA的第6和第7引脚。
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;       // ARR
    TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;       // PSC
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
  • 定义一个定时器时间基础初始化结构体 TIM_TimeBaseInitStructure
  • 设置定时器的时钟分割为1(即不分割)。
  • 设置定时器的计数模式为向上计数。
  • 设置自动重装载寄存器(ARR)的值为65535,这意味着定时器的计数范围为0到65535。
  • 设置预分频器(PSC)的值为0,这意味着没有额外的分频。
  • 设置重复计数器的值为0。
  • 调用 TIM_TimeBaseInit 函数初始化TIM3的时间基础。
    TIM_ICInitTypeDef TIM_ICInitStructure;
    TIM_ICStructInit(&TIM_ICInitStructure);
    TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
    TIM_ICInitStructure.TIM_ICFilter = 0xF;
    TIM_ICInit(TIM3, &TIM_ICInitStructure);
    TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
    TIM_ICInitStructure.TIM_ICFilter = 0xF;
    TIM_ICInit(TIM3, &TIM_ICInitStructure);
  • 定义一个输入捕获初始化结构体 TIM_ICInitStructure
  • 初始化该结构体。
  • 设置第1通道(对应GPIOA6)的输入捕获滤波器为16个时钟周期(0xF),这有助于抑制噪声。
  • 初始化TIM3的第1通道。
  • 设置第2通道(对应GPIOA7)的输入捕获滤波器为16个时钟周期。
  • 初始化TIM3的第2通道。
    TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
  • 配置TIM3为编码器模式,使用TI1和TI2通道。
  • 设置两个通道的输入极性都为上升沿。
    TIM_Cmd(TIM3, ENABLE);
  • 使能TIM3定时器。
}
  • 结束函数 Encoder_Init
int16_t Encoder_Get(void)
{
    int16_t Temp;
    Temp = TIM_GetCounter(TIM3);
    TIM_SetCounter(TIM3, 0);
    return Temp;
}
  • 定义一个函数 Encoder_Get 用于获取当前的计数值。
  • 读取TIM3的计数器值到变量 Temp
  • 清零TIM3的计数器。
  • 返回计数器值。
  • 12
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FightingLod

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值