登录/注册

STM32通用定时器编码器

STM32通用定时器编码器

更多

好的,我们来详细解释一下 STM32 通用定时器 (TIMx) 的编码器接口模式(Encoder Interface Mode)。这是一个非常有用的功能,用于直接读取旋转编码器(如正交增量式编码器)的信号。

核心功能:

STM32 的通用定时器内置了硬件编码器接口。它能自动读取连接在定时器通道 CH1 和 CH2 引脚上的正交编码器输出的两相信号(通常称为 A 相和 B 相),并根据这两相信号的相位关系(超前/滞后)自动递增或递减定时器的计数器 CNT 寄存器。这样,你只需读取 CNT 的值,就能精确知道编码器转动的方向和位置变化量(脉冲数)。

为什么使用它?

  1. 硬件处理: 免去了软件通过外部中断或 GPIO 轮询来解码编码器信号的复杂性和资源消耗(CPU 负载)。
  2. 高精度与速度: 硬件处理速度极快,能可靠捕获高速旋转编码器的信号,不易丢失脉冲。
  3. 方向辨别: 硬件自动根据相位关系判断方向,并据此递增或递减计数器。
  4. 简化软件: 软件只需定期读取计数器值即可获取位置和方向信息。
  5. 溢出处理: 计数器溢出时可以利用定时器中断或 DMA 来处理。

工作原理:

  1. 编码器输出: 正交增量式编码器输出两路相位差为 90 度(1/4 周期)的方波信号:A 相和 B 相。
  2. 方向判断:
    • 当编码器正转时(假设顺时针),相位关系通常是 A 相超前 B 相 90 度
    • 当编码器反转时(逆时针),相位关系变为 B 相超前 A 相 90 度
  3. 定时器模式: 将定时器配置为编码器接口模式。该模式本质上是配置定时器工作于一种特殊的外部时钟源模式
  4. 计数器操作:
    • 定时器会根据连接到 CH1 和 CH2 引脚上的 A、B 相信号组合,在每个有效信号跳变沿(上升沿、下降沿或双边沿,取决于配置)更新计数器。
    • 硬件自动检测信号相位关系:
      • 如果检测到是正转的相位关系 (A 超前 B),计数器 CNT 递增
      • 如果检测到是反转的相位关系 (B 超前 A),计数器 CNT 递减
    • 这样,计数器 CNT 的值就反映了 相对于初始位置的净脉冲数(正向脉冲减去反向脉冲)。
  5. 计数模式: 在编码器模式下,计数方向由编码器信号决定,用户配置的计数器方向 (DIR) 位会实时反映当前的方向(0 表示递增/正转,1 表示递减/反转)。计数模式通常是“向上/向下”计数模式。
  6. 溢出与中断: 当计数器达到自动重装载寄存器 ARR 的值时向上溢出,回到 0 时向下溢出。可以启用对应的更新中断来处理溢出事件(例如,记录转动的圈数)。

典型配置步骤 (以常见库函数/HAL库为例):

  1. 使能时钟: 使能 TIMx 外设时钟和对应的 GPIO 时钟。
  2. 配置 GPIO:
    • 将 CH1 和 CH2 对应的 GPIO 引脚配置为复用功能模式 (Alternate Function)。
    • 选择合适的复用功能编号(AFx),确保映射到正确的 TIMx_CH1 和 TIMx_CH2。
    • 通常配置为浮空输入上拉输入(具体根据编码器输出特性决定)。
  3. 配置定时器基本参数 (可选但有推荐):
    • 设置 TIM_HandleTypeDef.Init.Prescaler = 0; (不分频)。
    • 设置 TIM_HandleTypeDef.Init.CounterMode = TIM_COUNTERMODE_UP; (虽然方向由硬件自动控制,但模式通常设置为向上)。
    • 设置 TIM_HandleTypeDef.Init.Period = 0xFFFF; 或所需的最大计数值(自动重装载寄存器 ARR)。ARR 决定了计数器在溢出前能累积的最大脉冲数。 对于 16 位计数器,最大为 65535 (0xFFFF)。
    • 设置 TIM_HandleTypeDef.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    • 设置 TIM_HandleTypeDef.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; 或根据需要启用。
  4. 配置编码器模式 (关键步骤): 这通常通过配置定时器的 从模式控制 (Slave Mode Control) 来实现。
    • HAL 库示例 (STM32CubeMX/HAL):
      TIM_Encoder_InitTypeDef sEncoderConfig = {0};
      sEncoderConfig.EncoderMode = TIM_ENCODERMODE_TI12; // 常用模式,在TI1和TI2的边沿计数
      // 选择输入捕获滤波器(根据信号噪声情况调整)
      sEncoderConfig.IC1Filter = 0xF; // 0x0~0xF, 越大滤波时间越长
      sEncoderConfig.IC1Polarity = TIM_ICPOLARITY_RISING; // 触发边沿选择
      sEncoderConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI; // 通道1映射到TI1输入
      sEncoderConfig.IC1Prescaler = TIM_ICPSC_DIV1; // 输入捕获预分频(通常为1)
      sEncoderConfig.IC2Filter = 0xF; // 同通道1
      sEncoderConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
      sEncoderConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI; // 通道2映射到TI2输入
      sEncoderConfig.IC2Prescaler = TIM_ICPSC_DIV1;
      if (HAL_TIM_Encoder_Init(&htimx, &sEncoderConfig) != HAL_OK) // htimx是你的定时器句柄
      {
          Error_Handler();
      }
      • .EncoderMode:
        • TIM_ENCODERMODE_TI1:仅使用 TI1 (通道1) 的边沿计数(方向由 TI2 决定)。
        • TIM_ENCODERMODE_TI2:仅使用 TI2 (通道2) 的边沿计数(方向由 TI1 决定)。
        • TIM_ENCODERMODE_TI12最常用。在 TI1 和 TI2 两个边沿都计数(4 倍频模式)。例如,一个物理脉冲周期内有四个计数边沿(A 相上升沿、A 相下降沿、B 相上升沿、B 相下降沿)。这提供了 4 倍的分辨率,但计数器变化速度也是最快的(4 倍频)。
    • 标准外设库 (StdPeriph) 示例:
      TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
      TIM_ICInitTypeDef TIM_ICInitStructure;
      // ... 配置基本时基参数 (Prescaler = 0, Period = 0xFFFF, ClockDivision, CounterMode) ...
      TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);
      // 配置通道1作为输入
      TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
      TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; // 或 TIM_ICPolarity_BothEdge
      TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
      TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
      TIM_ICInitStructure.TIM_ICFilter = 0x0; // 滤波系数
      TIM_ICInit(TIMx, &TIM_ICInitStructure);
      // 配置通道2作为输入
      TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
      TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; // 或 TIM_ICPolarity_BothEdge
      TIM_ICInit(TIMx, &TIM_ICInitStructure);
      // 配置编码器模式 (本质是设置从模式)
      TIM_SelectSlaveMode(TIMx, TIM_SlaveMode_Encoder1); // TIM_SlaveMode_Encoder1, Encoder2, Encoder3
      // 或
      TIM_EncoderInterfaceConfig(TIMx, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
      • TIM_SlaveMode_Encoder1/2/3TIM_EncoderMode_TI1/TI2/TI12:含义与 HAL 库的 .EncoderMode 类似,决定使用哪个通道的边沿计数。
      • TIM_ICPolarity:设置捕获极性(上升沿、下降沿或双边沿触发计数)。.TIM_EncoderMode_TI12 模式通常需要两个通道都配置为双边沿 (TIM_ICPolarity_BothEdge) 才能实现真正的 4 倍频计数。
  5. (可选) 启用中断/DMA:
    • 如果需要处理计数器溢出(更新事件)或捕获事件,可以启用更新中断 (Update Interrupt) 或捕获中断(较少用于编码器模式本身)。
    • 配置 NVIC (嵌套向量中断控制器) 设置中断优先级和使能。
  6. 启动编码器接口:
    • HAL 库: HAL_TIM_Encoder_Start(&htimx); // 只启动计数器
    • HAL_TIM_Encoder_Start_IT(&htimx); // 启动计数器并使能更新中断
    • 标准库: TIM_Cmd(TIMx, ENABLE); // 使能定时器
    • 如果启用了中断,还需调用 TIM_ITConfig(TIMx, TIM_IT_Update, ENABLE);

应用:

  1. 读取位置:
    int32_t current_position = (int32_t)__HAL_TIM_GET_COUNTER(&htimx); // HAL 库
    // 或
    int32_t current_position = (int32_t)TIM_GetCounter(TIMx); // 标准库

    这个值表示从启动或上次清零后,编码器转动的净脉冲数(正向脉冲 - 反向脉冲)。

  2. 读取方向:
    if (__HAL_TIM_IS_TIM_COUNTING_DOWN(&htimx)) { // HAL库判断是否向下计数
        // 当前为反转方向
    } else {
        // 当前为正转方向
    }
    // 标准库通常读取 TIMx->CR1 寄存器的 DIR 位
    if ((TIMx->CR1 & TIM_CR1_DIR) == TIM_CR1_DIR) {
        // 当前为向下计数 (反转)
    } else {
        // 当前为向上计数 (正转)
    }
  3. 测量速度 (RPM/转速):
    • 方法 1 (软件定时采样):在固定时间间隔 T(例如 100ms)内,读取两次计数器值。速度 = (Δ计数 / T) / (每转脉冲数 倍频数) 60 [单位:RPM]。Δ计数 = current_position - previous_position。注意处理计数器溢出。
    • 方法 2 (输入捕获):配置另一个定时器或同一个定时器的另一个通道(如果支持)用于输入捕获模式,捕获编码器信号中某一相(如 Z 相/Index 信号)的周期来计算速度。这通常更适合测量平均速度或中低速。
  4. 测量距离/角度: 距离 = current_position / (每转脉冲数 * 倍频数) * [传动比] * 圆周运动周长 / 360度。需要知道机械结构和编码器规格。

重要注意事项:

  1. GPIO 映射: 务必确保编码器的 A、B 相接在所选定时器的 CH1 和 CH2 对应的 GPIO 引脚上,并配置为正确的复用功能
  2. 倍频模式: TI12 (4 倍频) 模式分辨率最高,但计数器变化最快。如果你的编码器转速很高且 ARR 设置不够大,可能导致计数器频繁溢出。如果速度过高或不需要高分辨率,可选用 TI1TI2 (2 倍频) 模式。
  3. 信号质量: 如果编码器信号有噪声,需要使用输入捕获滤波器 (ICFilter)。值越大滤波越强,但会降低最高能响应的信号频率。
  4. 计数器溢出:
    • ARR 的值决定了计数器的最大范围。例如,16位计数器 ARR = 0xFFFF,最大计数 ±32767 (当初始值设为 0 时)。
    • 对于长距离或高分辨率编码器,计数器容易溢出。解决方案:
      • 启用更新中断 (Update Interrupt),在中断服务程序 (ISR) 中维护一个软件计数器(如 overflow_count)。总位置 = (uint32_t)overflow_count * (ARR + 1) + current_position。注意处理方向。
      • 使用具有 32 位计数器的定时器 (如某些 STM32 的高级定时器 TIM2/TIM5)。
      • 使用定时器的编码器模式结合定时器级联。
  5. 起始位置: 上电或初始化后,计数器值是不确定的。通常需要在机械零点或已知位置时,通过软件 (__HAL_TIM_SET_COUNTERTIM_SetCounter) 将计数器清零或设置为一个初始值。
  6. 兼容性: 并非所有通用定时器都支持编码器模式。请查阅你所使用 STM32 型号的参考手册 (Reference Manual) 中关于 TIMx 章节的说明,确认具体哪个定时器支持此功能(通常是 TIM2, TIM3, TIM4, TIM5 等)。

总结:

STM32 的通用定时器编码器接口模式是一个强大的硬件功能,为读取正交编码器提供了一种高效、可靠的方法。通过正确配置定时器和 GPIO,开发者可以轻松获取精确的位置信息和方向信息,极大地简化了电机控制、位置反馈、转速测量等应用的设计。关键在于理解其工作原理,并根据实际应用需求(编码器分辨率、最高转速)配置好计数模式、ARR 大小、滤波器和处理好溢出问题。

查阅你所使用 STM32 系列的具体参考手册和对应的外设库用户手册(HAL 或 StdPeriph)是成功配置和应用该功能的关键。

定时器是不是有编码器输入功能?

你好,我想请教一下定时器是不是有编码器输入功能,是高级定时器和通用

2025-03-11 07:07:44

STM32CubeMx定时器编码器模式基本使用方法

增量式编码器在实际应用中还是很常见。stm32的定时器带的也有编码器模式

2023-06-01 14:36:10

STM32通用定时器

STM32F1 的定时器非常多,由 2 个基本定时器(TIM6、TIM7)、4 个通用

2023-02-10 14:47:04

STM32F103-定时器编码器模式和高级定时器输出互补的PWM信号

STM32F103-定时器编码器模式和高级定时器输出互补的PWM信号刚使

资料下载 王鹏 2022-01-14 12:53:16

STM32-通用定时器-定时器中断

1STM32的定时器STM32F103ZET6一共有8个定时器,其中分别

资料下载 张生 2021-11-26 15:36:04

STM32——高级定时器通用定时器、基本定时器的区别

STM32——高级定时器、通用定时器、基本

资料下载 362163 2021-11-26 15:21:05

[STM32]通用定时器的使用

STM32的通用定时器的定时、输出PWM功能的使用本次还是使用发光二极管

资料下载 佚名 2021-11-22 19:06:03

STM32单片机定时器1设置成为AB项编码器模式

STM32单片机定时器1设置成为AB项编码器模式大家好·,我是DXZ,这篇博客是使用S

资料下载 佚名 2021-11-18 15:21:01

详解stm32定时器编码器模式

增量式编码器在实际应用中还是很常见。stm32的定时器带的也有编码器模式

2023-01-19 09:14:00

STM32F407定时器编码器模式简介

STM32F407定时器编码器模式

2022-03-31 17:14:16

定时器中断来实现stm32定时

用来定时、输入捕获、pwm输出、正交编码器等,功能强大。stm32通用

2022-01-06 06:46:34

电机控制基础3——定时器编码器模式使用与转速计算

路脉冲,如果使用上一篇介绍的方法,编程就较为复杂。还好单片机的通用定时器具有 专门的正交编码器接口 ,只需配置相应的寄存

2021-08-30 17:26:42

关于定时器编码器的应用

实验目的:刚开始接触关机电机检测领域,准备探索关于定时器编码器的应用,用来检测脉冲数,从而进行转速的检测。使用芯片:STM32F407使用平台:

2021-08-19 07:32:06

STM32通用定时器有哪些问题

或者由内部/外部触发计数)输入捕获输出比较支持针对定位的增量(正交)编码器和霍尔传感器电路触发输入作为外部时钟或者按周期的电流管理STM32 的

2021-08-05 07:31:35

使用STM32F103ZET6通用定时器编码器模式对反馈信号进行计数

使用正点原子的库,如有错误欢迎指正霍尔编码电机我用的电机上的霍尔编码器是这样的两个反馈信号输出,两者相位差90°连接示波器后显示的波形如下测速方

2021-08-05 06:49:26
7天热门专题 换一换
相关标签