正交编码器解码:从 A/B 两相读出方向与位置
更新时间:2026-09-24。本文是「集成电路大类 · 芯片设计」入门层(beginner) 的一篇数字逻辑正文。鼠标滚轮滚一格、音量旋钮拧一档、伺服电机转过半圈——这些「转了多少、往哪转」的问题,增量式旋转编码器都用两路错开 90° 的方波来回答。这一篇看怎么用纯数字逻辑把这两相信号解码成带符号的位置,以及怎么顺带读出转速。它直接用到 格雷码与码制转换、脉冲同步与边沿检测 和 计数器与移位寄存器 三处基础。
本文要回答的问题
- 编码器输出的 A、B 两相为什么要错开 90°?怎么从「谁领先」判断正转和反转?
- 为什么把 (A,B) 当成一个 2-bit 格雷码、在四状态环上走,就能自动得到加计数和减计数?
- 1x / 2x / 4x 解码差在哪?4 倍频为什么能不增加码盘线数就白拿四倍分辨率?
- 外部信号要不要同步?机械编码器的触点抖动、Z/index 零位脉冲、计数器溢出分别怎么处理?
- 转速怎么测?M 法和 T 法各适合什么速度区间?
一、编码器在量什么:从机械转角到两路方波
先说清楚被解码的对象。增量式编码器的核心是一个装在转轴上的码盘:盘上均匀分布着透光和遮光相间的刻线(光电式),或是交替排布的磁极(霍尔式),再或者干脆是一组弹性触点(机械旋钮式)。两个检测元件在物理位置上错开四分之一个刻线节距,于是轴转动时它们输出的两路方波 A、B 频率相同、相位恰好相差 90°——英文叫 quadrature(正交),名字由此而来。
一个完整的正交周期(A、B 都走完一个高低循环)对应轴转过一个刻线节距。码盘刻了多少条线,转一圈就有多少个这样的周期,常见规格是每转 100、1000、2500 线。注意「增量」二字:它只在轴动的时候发脉冲,脉冲数告诉你相对位移,却不告诉你上电那一刻轴停在什么绝对角度。这一点决定了后面必须配一个零位相来找原点。
应用场合决定档次:手转的音量旋钮、鼠标滚轮用廉价机械触点式,边沿脏、抖动重;伺服电机、电梯曳引机、数控主轴用光电式,每转上千线、边沿干净,对解码逻辑的速度要求也高。
二、相位差 90°:谁领先,方向就归谁
只有一路方波时,数它的边沿可以知道「动了几个刻度」,但正转和反转数出来的数一模一样——方向信息丢了。错开 90° 的第二相就是专门用来补这个信息的。规律只有一句:
- 正转时 A 相领先 B 相,A 先跳,B 过四分之一周期才跟着跳;
- 反转时 B 相领先 A 相,两相的先后顺序整个颠倒过来。
下图画出正转时两相信号在一个周期内的相对位置,并标出四个跳变沿的先后。

读图:在时刻 1,A 先从 0 跳到 1,此时 B 仍是 0;到时刻 2,B 才跳到 1。也就是说,A 的上升沿发生时 B 为低。如果轴反过来转,先跳的是 B,A 上升沿时 B 已经是高电平。于是最朴素的方向判据立刻成立:在 A 的某个边沿上看 B 的电平——B 低是一个方向,B 高就是另一个方向。这个「边沿时刻看另一相电平」的直觉,是后面所有解码方式的根。
三、状态环:{A,B} 就是一个 2-bit 格雷码
把任意时刻两相的电平拼成一个 2-bit 值 {A,B},它只有四种取值:00、01、11、10。转动时这个值沿一个四状态环变化,而且因为两相边沿错开、永远不会同时跳,所以每一步只变一位——这正是 格雷码相邻状态只变 1 bit 的性质。
图的读法:外圈顺时针方向 00→01→11→10→00 是正转,每走一格位置计数加一;逆时针是反转,每走一格减一。于是解码逻辑退化成一张状态转换表:把当前拍的 {A,B} 和上一拍比较——沿环前进就 +1,后退就 −1,两拍相同说明轴静止、不动,而 00 与 11 之间、01 与 10 之间这种一次变两位的「对角跳变」物理上不可能发生,只能是毛刺或亚稳,直接丢弃。位置计数器用带符号数,它的正负号就是净方向,累计值就是净位移。
下面是这个思路的可综合描述,注意外部 A/B 相对本时钟是异步信号,先打两拍再用。
// 同步 + 4x 正交解码(概念)
logic signed [W-1:0] pos;
logic [1:0] ab_q1, ab_q2; // 两级同步外部 A/B
always_ff @(posedge clk or negedge rst_n)
if (!rst_n) {ab_q2,ab_q1} <= 4'b0;
else {ab_q2,ab_q1} <= {ab_q1, {a_in,b_in}};
logic [1:0] prev;
always_ff @(posedge clk or negedge rst_n)
if (!rst_n) prev <= 2'b0;
else prev <= ab_q2;
// 前进环 00->01->11->10,后退反之;对角跳变保持不动
always_ff @(posedge clk or negedge rst_n)
if (!rst_n) pos <= '0;
else unique case ({prev, ab_q2})
4'b00_01,4'b01_11,4'b11_10,4'b10_00: pos <= pos + 1'b1; // 正转
4'b01_00,4'b11_01,4'b10_11,4'b00_10: pos <= pos - 1'b1; // 反转
default: pos <= pos; // 静止/非法
endcase核心加法器来自 可逆计数器,整张 case 表就是上图状态环的直译,没有任何乘法或角度运算。
四、1x / 2x / 4x:把分辨率用到极限
一个正交周期里 A 有一个上升沿和一个下降沿,B 同样,共四个跳变。用其中几个沿计数,就有三档解码方式:
| 解码方式 | 计数的边沿 | 每周期计数 | 方向依据 | 典型用途 |
|---|---|---|---|---|
| 1x | 只数 A 的一个沿(如上升沿) | 1 | 该沿时刻 B 的电平 | 低成本旋钮、简单菜单输入 |
| 2x | 数 A 的上升沿和下降沿 | 2 | 各沿时刻 B 的电平 | 一般调速、分辨率要求不高 |
| 4x | A、B 全部四个沿都数 | 4 | 状态环前进/后退 | 伺服、步进、运动控制默认 |
4x 模式就是第三节状态环的做法:每检测到一次合法的单 bit 跳变就计一次数。它的价值非常实在——码盘还是那个 1000 线的码盘,每转的计数却从 1000 变成 4000,机械成本一分钱不加,位置分辨率提高四倍。角度折算也简单:一个 4x 计数等于 360°/(线数×4),1000 线编码器就是每计数 0.09°。代价只是解码时钟要跟得上最高脉冲频率,这对今天的逻辑毫无压力,所以电机控制里几乎一律 4x。
挑档位时别只盯分辨率:低速手拧旋钮用 4x 会让每格「咔哒」对应四个计数,人机手感反而怪,这种场景 1x 更合适。
五、同步、去抖、Z 相和计数宽度
信号进逻辑之前有四道工程关,每一道对应一个真实事故。
先同步。 A、B 来自转动的外部世界,和本地时钟没有任何相位关系,直接进寄存器可能撞上亚稳态。标准做法是每个信号各打两拍再解码(见 脉冲同步与边沿检测)。两级同步引入的延迟固定且相同,不影响两相之间的相位关系。
再去抖。 机械触点式编码器在触点闭合、断开的几毫秒内会快速通断,一个沿抖出十几个脉冲。若不处理,状态环上就会反复出现「前进一格又后退一格」的小环,计数来回窜,表现为数值漂移。常见办法是在同步之后加数字滤波:用一个远高于抖动频率的采样时钟连续采 N 次,N 次电平一致才认这次跳变;或者片外加 RC 滤波加施密特触发器。光电编码器边沿干净,这一级可以放宽甚至省掉。
Z/index 找零。 多数编码器还有第三相 Z(也叫 index):每转一圈只输出一个窄脉冲,宽度通常等于一个正交节距。增量编码器上电时位置是未知的,需要做一次「找零」(homing)——让轴缓慢转动,捕获 Z 脉冲的瞬间把位置计数器清零(或装入约定值),从此之后的相对计数才有绝对角度意义。精密场合会在 Z 有效的同时再卡 A/B 状态,使零位精确到某个 4x 计数上。
位宽与漏读。 计数器位宽要按最坏情况估:最大转速 × 每转线数 × 4 倍频 × 两次读取的最长间隔,留足余量,32 位对绝大多数应用够用。系统里通常硬件计数、硬件在 Z 相和计数器满时发中断,微处理器定期读数,绝不能靠软件中断逐个数脉冲——高速时漏一个沿,位置就永久偏差一个计数。
六、顺带测转速:M 法与 T 法
有了脉冲流,转速只是单位时间内的计数,但低速和高速要反过来测,这和 频率与周期测量 是完全同一对方法。
| M 法(测频) | T 法(测周期) | |
|---|---|---|
| 做法 | 固定闸门时间内数正交脉冲个数 | 测相邻两个脉冲之间的时钟周期数 |
| 量纲 | 转速 = 脉冲数 / 闸门时间 | 转速 = 时钟频率 / 脉冲间隔计数 |
| 适合 | 高速:闸门内脉冲多,量化误差小 | 低速:脉冲间隔长,计时计数值大、分辨细 |
| 低速表现 | 闸门内只有一两个脉冲,误差极大 | 好 |
| 高速表现 | 好 | 脉冲间隔太短,计时分辨率不足 |
举例:闸门 10 ms,轴每转发 4000 个 4x 脉冲。高速时闸门内数到 2000 个,对应每秒 50 转,±1 个脉冲的量化误差只有万分之五;可如果低速到一转发 200 ms,闸门里可能只有 0 或 1 个脉冲,读数直接没法用——这时改用 T 法,测两个脉冲间隔约 50 μs,用 100 MHz 时钟数出约 5000 个周期,分辨率就回到几千分之一。实际驱动器常做 M/T 切换:以某个转速为界,高速用 M 法、低速用 T 法,全段都保持细分辨率。测速结果送给速度环,和 PWM 电机驱动 一起就凑齐了一个最基本的电机调速闭环。
这一篇在知识体系里的位置
本篇属于芯片设计入门层的数字逻辑应用,回答「外部世界的连续转动怎么进数字系统」。向基础读,方向判据的合法性来自 格雷码与码制转换,异步信号的处理来自 脉冲同步与边沿检测,累计位移靠 计数器与移位寄存器;向测量方法读,M/T 法在 频率与周期测量 里有更一般的讨论;向系统应用读,MCU/FPGA 的定时器编码器外设见 接口与定时器外设,配合 PWM 电机驱动 即构成电机运动控制的最小闭环。理解了「相位差携带方向、状态环完成加减」这句话,再看任何芯片手册里的编码器模式寄存器都不会陌生。
总结
正交编码器解码就是:A、B 两相相位差 90°,正转 A 领先、反转 B 领先;把 {A,B} 看作 2-bit 格雷码,它沿 00→01→11→10 的四状态环每次只变一位地前进或后退,比较相邻两拍状态即可让位置计数 +1 或 −1,对角两位跳变按噪声丢弃;数两相全部四个沿的 4x 模式不加码盘线数就把分辨率提高四倍,是电机控制默认;信号先两级同步防亚稳、机械编码器再做去抖,Z/index 相每转一个脉冲用于上电找零,计数器位宽按最大转速×线数×4 选取并由硬件计数防漏读,测速则高速用固定闸门数脉冲的 M 法、低速用测脉冲间隔的 T 法。