STM32F103RCT6 --定时器TIM3 读取编码器

1. 编码器

编码器是一种常见的输入设备,用于检测 旋转物体 的位置和方向。编码器通常由两个部分组成:一个固定的 编码器盘 和一个放置在旋转轴上的 编码器探头。当旋转轴转动时,编码器探头会扫描编码器盘上的编码器刻线,并产生相应的脉冲输出,从而可以计算出旋转轴的位置和方向
STM32芯片的TIM模块提供了三种编码器模式:正交编码器模式、**反向编码器模式 **和 计数器模式。其中,正交编码器模式是最常用的一种,它可以实现对编码器正转和反转的计数。在正交编码器模式下,TIM模块的两个输入捕获通道分别接收编码器的两路脉冲信号,并且自动进行相位差比较,从而可以确定当前编码器的旋转方向和距离移动量。

需要注意的是,在使用编码器模式时,需要配置正确的计数模式和方向,以确保计数器在编码器旋转过程中能够正确地统计脉冲数量。此外,编码器模式还可以与DMA传输和中断等其他功能结合使用,以满足特定的应用需求。

2. 以下是一个基于STM32 HAL库的编码器模式使用示例,使用TIM3,详细说明了如何配置TIM模块以读取编码器的旋转方向和数量。

#include "stm32f1xx_hal.h"

TIM_HandleTypeDef htim3;

void TIM3_Init(void)
{
  TIM_Encoder_InitTypeDef sConfig = {0};
	
  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 0;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = 65535;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  
  sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
  sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
  sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
  sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
  sConfig.IC1Filter = 0;
  sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
  sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
  sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
  sConfig.IC2Filter = 0;
	
  if (HAL_TIM_Encoder_Init(&htim3, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
}

int main(void)
{
  HAL_Init();
  TIM3_Init();
	
  // 使能TIM3计数器
  HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);
  
  while(1)
  {
    // 读取TIM3计数器的值
    int16_t count = (int16_t)(htim3.Instance->CNT);
    if (count > 0) {
      // 正转
    } else if (count < 0) {
      // 反转
    } else {
      // 停止
    }
  }
}

在代码中,首先通过HAL库的TIM_Encoder_InitTypeDef结构体配置了TIM3的计数器模式和编码器模式,并启用了计数器。然后,在主循环中读取TIM3计数器的值,并根据其变化判断编码器的旋转方向(正转或反转)。需要注意的是,TIM3的计数器值为16位有符号整数,可以表示-32768到+32767之间的范围,因此在使用时需要考虑溢出和数据类型转换等问题。

3. HAL_TIM_Encoder_Init()是STM32 HAL库中的一个函数,用于初始化TIM模块的编码器模式参数。

函数原型如下:

HAL_StatusTypeDef HAL_TIM_Encoder_Init(TIM_HandleTypeDef *htim, TIM_Encoder_InitTypeDef *sConfig);

其中,htim是指向TIM_HandleTypeDef结构体的指针,用于指定要初始化的TIM实例和其相关参数;sConfig是指向TIM_Encoder_InitTypeDef结构体的指针,用于指定编码器模式的参数,包括编码器模式、IC输入信号的极性、选择和分频器等。

函数返回值为HAL_StatusTypeDef类型,表示函数执行的状态。如果返回值为HAL_OK,则表示初始化成功。如果返回值为其他值,则表示初始化失败。

需要注意的是,在使用HAL_TIM_Encoder_Init()函数前,需要先调用HAL_TIM_Base_Init()函数对TIM基本参数进行配置,例如计数模式、时钟分频等。此外,在初始化完成后,需要调用HAL_TIM_Encoder_Start()函数启动编码器模式,并通过htim->Instance->CNT读取编码器计数器的当前值。

4. HAL_TIM_Encoder_Init函数是HAL库对STM32的TIM模块配置和控制的封装,它的实现分为两部分:初始化TIM寄存器和启动编码器模式。

首先,函数通过传入的参数,使用HAL库内部的寄存器配置函数对TIM相关寄存器进行初始化。具体来说,代码会将TIM寄存器的相应位域设置为编码器模式所需的值。例如:

/* 选择编码器模式 */
htim->Instance->SMCR &= ~(TIM_SMCR_SMS);
htim->Instance->SMCR |= (uint32_t)sConfig->EncoderMode;
    
/* 配置IC输入信号极性和选择 */
htim->Instance->CCER &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP);
htim->Instance->CCER &= ~(TIM_CCER_CC2P | TIM_CCER_CC2NP);
htim->Instance->CCMR1 &= ~(TIM_CCMR1_CC1S | TIM_CCMR1_CC2S);
	
htim->Instance->CCER |= (uint32_t)sConfig->IC1Polarity | sConfig->IC2Polarity;
htim->Instance->CCMR1 |= (uint32_t)sConfig->IC1Selection | sConfig->IC2Selection;

然后,函数通过调用HAL库内部的启动函数,使TIM进入编码器模式并开始计数、计数器自动清零。例如:

if(HAL_IS_BIT_SET(htim->Instance->CR1, TIM_CR1_DIR))
{
  htim->State = HAL_TIM_STATE_READY;
  return HAL_ERROR;
}
else
{
  TIM_ENCODER_SET_STATE(htim, HAL_TIM_STATE_BUSY);
  /* Reset the Encoder Data */
  __HAL_TIM_SET_COUNTER(htim, 0x0000U);
  
  /* Enable the encoder interface channels */
  htim->Instance->CCER |= (TIM_CCER_CC1E | TIM_CCER_CC2E);
  /* Enable the Counter */
  __HAL_TIM_ENABLE(htim);
	
  TIM_ENCODER_RESET_HANDLE_STATE(htim);
	
  return HAL_OK;
}

HAL库是由STM32官方提供的代码库,其源码并不公开。
需要注意的是,启动编码器模式前需要判断TIM计数器的方向是否正确,否则会返回错误状态。在启动编码器模式后,函数会将编码器计数器自动清零,并通过设置相关寄存器,使TIM开始从IC输入信号中接收计数脉冲,并根据脉冲的数量自动更新计数器值。

5. 正转、反转和停止编码器的代码示例如下:

5.1 正转:

使用HAL_TIM_Encoder_Start函数启动编码器模式后,只需使用HAL_GPIO_WritePin函数将编码器的方向引脚设置为对应的电平即可实现正转。例如,如果编码器的方向引脚为PA6,并且编码器的正转方向需要将该引脚设置为高电平,则可以执行以下代码:

// 启动编码器计数模式
HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);

// 将编码器的方向引脚设置为高电平,实现正转
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET);

5.2 反转:

与正转类似,只需要将编码器的方向引脚设置为相反的电平即可实现反转。例如,如果编码器的方向引脚为PA6,并且编码器的反转方向需要将该引脚设置为低电平,则可以执行以下代码:

// 启动编码器计数模式
HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);

// 将编码器的方向引脚设置为低电平,实现反转
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET);

5.3 停止:

停止编码器的方法有两种,一种是使用HAL_TIM_Encoder_Stop函数停止编码器计数模式,另一种是将编码器的方向引脚设置为高阻态,停止其信号输出。以下是两种方法的示例代码:

(1)使用HAL_TIM_Encoder_Stop函数停止编码器计数模式:

// 停止编码器计数模式
HAL_TIM_Encoder_Stop(&htim3, TIM_CHANNEL_ALL);

(2)将编码器的方向引脚设置为高阻态:

// 将编码器的方向引脚设置为高阻态,停止其信号输出
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_MODE_ANALOG);

以上代码只针对编码器的方向引脚,如果编码器还有其他控制引脚,记得对其进行相应的操作。同时,如果需要准确读取编码器计数值,建议在停止编码器前调用HAL_TIM_Encoder_GetCounter函数获取当前编码器的计数值。

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值