编码器接口与测速详解
笔记 / 嵌入式
引言
算一笔账:2500 线增量编码器、4 倍频解码、电机 6000 rpm 满速,每秒 100 转 × 10000 个计数 = 1 MHz 的边沿流。用外部中断数边沿,CPU 每 1 μs 被打断一次,没有余力执行其它代码。降倍频也不行:分辨率直接砍半,速度环低速就抖。
出路是让硬件替 CPU 数。STM32 通用定时器自带编码器接口模式:两路正交信号直接接进定时器,边沿由硬件计数,方向由硬件判别,CPU 只需按控制周期读一次计数器。1 kHz 的 FOC 速度环,读一次 CNT 的开销接近于零。
一、编码器是什么
增量式光电编码器的结构:光源(LED)+ 透镜把光聚成平行光束,打在码盘上。码盘是一个刻有辐射状透光缝隙的圆盘,随转轴旋转;缝隙后面的固定光栅与码盘缝隙形成遮光/透光节拍,光电检测器件把光脉冲变成电脉冲,经转换电路整形输出。

两组检测缝隙在空间上错开 1/4 个节距,所以输出信号 A、B 相位差恒为 90°,这就是「正交」的物理来源。多数编码器还有第三路输出 Z(Index,零位脉冲):码盘上单独开一条缝,每转输出一个窄脉冲,作为角度参考点。

两类编码器的差别:
| 类型 | 原理 | 上电后位置 | 典型场景 |
|---|---|---|---|
| 增量式 | 数脉冲,只输出”变了多少” | 未知,需回零 | 电机速度环、滚轮、3D 打印机 |
| 绝对式 | 码盘每一位独立编码(常为格雷码) | 天然可知 | 机器人关节、多圈计数、断电保持 |
绝对式单价高、线束多,电机控制里增量式仍是主流,代价是要额外处理两件事:上电时位置未知,以及丢脉冲会累积成误差。这两点在后面的章节里都会涉及。
二、正交信号与 4 倍频
A/B 相位差 90° 携带了方向信息:正转时 A 超前 B,反转时 B 超前 A。判别逻辑是:在谁的边沿上,看另一路的电平。A 上升沿时 B 为低是一个方向,B 为高是另一个方向。
一个 A 周期(码盘一条线)内有 4 个边沿:A↑、A↓、B↑、B↓。全都不放过,就是 4 倍频:
| 解码方式 | 每线计数 | 2500 线编码器每转计数 |
|---|---|---|
| 仅 A 相上升沿 | 1× | 2500 |
| A 相双沿 | 2× | 5000 |
| A/B 全部边沿 | 4× | 10000 |
线刻多密决定了物理分辨率,倍频只是把每个线周期细分成 4 份。它的实际作用是把量化误差压缩到 1/4 线以内,低速时速度估算显著变细。
线数与倍频必须一起核对。拿到一颗新编码器,先手动转一整圈看 CNT 增量:如果不等于「线数 × 4」,多半是倍频模式配错,速度换算会全线出错。
三、STM32 编码器接口模式
编码器接口建立在通用定时器的计数与输入捕获单元上,定时器基础见 单片机定时器与中断系统详解。F1 的 TIM2~TIM5 都支持编码器接口。配置只有两个要点:从模式控制寄存器 SMCR 的 SMS 位选计数方式,CC1/CC2 把两路信号接成输入捕获:
| SMS | 计数行为 | 倍频 |
|---|---|---|
| 001 | 仅 TI2 边沿计数,方向由 TI1 电平决定 | 2× |
| 010 | 仅 TI1 边沿计数,方向由 TI2 电平决定 | 2× |
| 011 | TI1/TI2 边沿都计数 | 4× |

这张图对应编码器接口的三个特性:
- 方向全自动:正转计数器加、反转减,抖动(正负边沿来回)自动抵消,不怕机械振动
- DIR 位只读:编码器模式下方向由硬件管理,读 CR1 的 DIR 位可以知道当前转向,但写它没用
- 输入滤波器可用:CCMR 里的 IC1F/IC2F 对输入做 N 次采样多数表决,电机碳刷火花、长线毛刺在这里挡掉
方向反了不必改接线:把 IC1Polarity 反转,等效于 A/B 相位对调,计数方向随之反转(RM0008 Figure 94 专门画了这件事)。改寄存器比重接编码器线方便。
四、测速三法
位置靠读 CNT 得到,速度需要另外计算。常用的有三种方法:
| 方法 | 原理 | 强项 | 弱项 |
|---|---|---|---|
| M 法(测频) | 固定时间窗 T 内数计数增量 ΔC | 高速精度好,实现最简单 | 低速窗内脉冲少,误差大 |
| T 法(测周) | 用高频时钟测相邻脉冲的间隔 | 低速精度好 | 高速周期太短,误差大 |
| M/T 法 | 同时测 ΔC 和 elapsed 时间,两者相除 | 全速段一致 | 实现最复杂 |
M 法相当于频率计在固定闸门时间内数脉冲,T 法相当于用高频时钟测量单个周期。两者的误差来源正好相反,低速时 M 法窗内脉冲太少,高速时 T 法的周期太短,所以有了兼顾全速段的 M/T 法。
M 法换算公式:
转速(rpm) = ΔC / (C_e × T) × 60
// C_e = 每转计数(线数 × 倍频),T = 采样窗口秒数
代入实数:10000 counts/rev、10 ms 窗口。1200 rpm 时 ΔC = 2000,±1 count 的量化误差只有 ±0.05%;降到 12 rpm,ΔC = 20,误差飙到 ±5%,速度环开始发抖,这就是低速要换 T 法或拉长窗口的原因。
T 法反过来:1 MHz 时钟测脉冲间隔,间隔 6000 个刻度 = 1 rpm,低速段测得又稳又准。
工程上多数情况走两条路:控制周期固定(如 1 kHz)用 M 法,代码只有三行;要求全速段精度的场合(力矩估计、观测器)才上 M/T。
五、HAL 配置示例
TIM2 编码器模式,PA0/PA1 接 A/B,4 倍频:
// 1. 时钟与引脚:PA0=TIM2_CH1(A), PA1=TIM2_CH2(B)
__HAL_RCC_TIM2_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef gpio = {0};
gpio.Pin = GPIO_PIN_0 | GPIO_PIN_1;
gpio.Mode = GPIO_MODE_INPUT; // F1 输入捕获引脚配成输入即可
gpio.Pull = GPIO_PULLUP; // 开路输出编码器必须上拉
HAL_GPIO_Init(GPIOA, &gpio);
// 2. 编码器模式:SMS=011,双边沿双通道 = 4 倍频
TIM_Encoder_InitTypeDef enc = {0};
htim2.Instance = TIM2;
htim2.Init.Prescaler = 0;
htim2.Init.Period = 0xFFFF; // 16 位计数器,ARR 拉满让回卷均匀
enc.EncoderMode = TIM_ENCODERMODE_TI12;
enc.IC1Polarity = TIM_ICPOLARITY_RISING; // 反转方向就改这里
enc.IC1Selection = TIM_ICSELECTION_DIRECTTI;
enc.IC1Filter = 0x0F; // 最强输入滤波,抗长线毛刺
enc.IC2Polarity = TIM_ICPOLARITY_RISING;
enc.IC2Selection = TIM_ICSELECTION_DIRECTTI;
enc.IC2Filter = 0x0F;
HAL_TIM_Encoder_Init(&htim2, &enc);
HAL_TIM_Encoder_Start(&htim2, TIM_CHANNEL_ALL);
控制周期里读速度——差值法,16 位回卷由有符号溢出自然吸收:
static uint16_t last_cnt = 0;
uint16_t now = __HAL_TIM_GET_COUNTER(&htim2);
int16_t diff = (int16_t)(now - last_cnt); // 回卷自动变号,不用 if 判断
last_cnt = now;
total_counts += diff; // int32_t 多圈累计位置
// 1 kHz 控制周期,10000 counts/rev:
float rpm = (float)diff * 60.0f / 10000.0f * 1000.0f;
Z 脉冲接 EXTI(或定时器 CH3 输入捕获,见 输出比较与输入捕获):中断里比对 CNT 与理论值,把累计误差一次清零。多圈场景下每转做一次校零,丢脉冲造成的漂移就被限制在一转之内,不会逐圈累加。
六、常见问题与注意事项
| 问题 | 原因 | 解决 |
|---|---|---|
| 位置读数来回抖、方向乱跳 | 振动边沿或长线毛刺 | 加大 IC1F/IC2F 滤波;信号线用双绞屏蔽 |
| 速度换算偏差固定比例 | 线数×倍频配错 | 手转一圈验证 CNT 增量 |
| 位置缓慢漂移 | 干扰丢脉冲、机械打滑 | 差分传输 + Z 脉冲校零 |
| 方向反了 | A/B 接反 | 反转 IC1Polarity,不用动线 |
| 低速时速度为 0 或剧烈跳动 | M 法窗内脉冲太少 | 拉长窗口、换 T 法/M-T 法 |
| 上电位置未知 | 增量式原理性限制 | 上电回零流程,或换绝对式编码器 |
两点工程经验:
- 长线必须差分:编码器装在电机轴上,驱动板在几米外,单端信号沿电机线束走容易耦合干扰。工业编码器标配 RS-422 差分(A+/A−/B+/B−/Z+/Z−),板端用 AM26LV32 这类差分接收器收回来再进定时器
- 编码器接口只是把计数搬进了外设,速度环的性能还取决于 PID 算法的基本原理和数学描述 的参数整定和 FOC 磁场定向控制的 C 语言实现 的电流环带宽,位置反馈的准确性是这两者的前提
总结
增量编码器把转动转换成两路正交脉冲,定时器的编码器接口把数脉冲的工作从 CPU 移到硬件:SMS 选倍频,CCx 配滤波与极性,CNT 给出位置,对 CNT 做差分得到速度。测速方法按速度段选 M 法、T 法或 M/T 法,精度的下限由「线数 × 倍频」决定。