4、绝对式编码器原理:单圈与多圈、SPI通信协议、数据帧解析、CRC校验

绝对式编码器,说白了就是「一上电就知道位置」的传感器。增量式编码器需要你转一圈去找零位,绝对式不用。这一点在FOC控制里太重要了——电机一启动,转子在哪儿,我立刻就知道,不需要「找零」这个过程。

我个人习惯把绝对式编码器分成两类:单圈和多圈。咱们先把这个概念理清楚。

4.1 单圈 vs 多圈:你到底需要多少圈?

单圈绝对式编码器,顾名思义,只能告诉你「在这一圈里的位置」。比如一个12位的单圈编码器,一圈有4096个位置。但如果你让电机转了两圈,它分不清现在是第二圈还是第一圈——因为位置值又回到0了。

多圈编码器就不一样了。它内部多了一个「圈数计数器」,可以记录你转了多少圈。比如12位单圈 + 12位多圈,总共24位数据,能记录4096圈内的绝对位置。

我在项目里遇到过一个问题:一个机械臂关节用了单圈编码器,每次上电后必须回零。后来换成多圈的,上电直接干活,省了回零这一步。你想想看,如果你的系统不允许「上电找零」(比如某些医疗设备),多圈就是刚需。

类型 数据范围 上电行为 典型应用
单圈绝对式 0 ~ (2^N - 1) 直接读取位置 伺服电机、云台
多圈绝对式 圈数 × 单圈分辨率 直接读取位置 机械臂、AGV

关键点:多圈编码器内部通常靠「齿轮传动」或「磁计数」来记录圈数。但注意,多圈计数是有上限的——超过最大圈数,计数器会溢出。选型时一定要算清楚你的应用会不会超圈。

4.2 SPI通信协议:绝对式编码器的「语言」

大多数绝对式编码器都用SPI通信。为什么?因为SPI是全双工、速度快、时序简单。你想想看,编码器要实时反馈位置,SPI的几MHz时钟完全够用。

SPI有四根线:SCLK(时钟)、MOSI(主出从入)、MISO(主入从出)、CS(片选)。对于编码器来说,MCU是主机,编码器是从机。主机发一个命令帧,编码器回一个数据帧。

我常用的SPI时序是这样的:

// 伪代码:读取绝对式编码器位置
uint16_t read_encoder_position(void) {
    uint16_t rx_data = 0;
    
    // 拉低CS,开始通信
    CS_LOW();
    
    // 发送读取命令(比如0xFFFF),同时接收数据
    rx_data = spi_transfer16(0xFFFF);
    
    // 拉高CS,结束通信
    CS_HIGH();
    
    return rx_data;
}

嗯,这里要注意:不同厂家的编码器,命令格式不一样。有的需要先发一个「读位置」指令,有的直接发任意数据就能读到位置。我建议你仔细看数据手册,别想当然。

我的经验:SPI时钟频率别拉太高。虽然编码器标称能跑10MHz,但实际线缆长了、干扰大了,容易丢数据。我一般用2~5MHz,稳定第一。

4.3 数据帧解析:从原始数据到角度值

SPI读回来的是一串二进制数,你得把它解析成角度。不同编码器的数据帧格式不同,但大体结构类似。

以某款14位单圈绝对式编码器为例,它的数据帧是16位:

位 15 14 13 12 ~ 1 0
含义 奇偶校验 数据有效标志 错误标志 位置数据(12位) 保留

解析步骤很简单:

  1. 检查错误标志位,如果置位,说明编码器内部故障,数据不可用。
  2. 检查数据有效标志,确保数据是新鲜的。
  3. 提取位置数据位(bit 12 ~ bit 1),得到一个0~4095的值。
  4. 换算成角度:角度 = (位置值 / 4096) × 360°。
// 解析14位编码器数据
float parse_encoder_frame(uint16_t raw) {
    // 检查错误标志 (bit 13)
    if (raw & (1 << 13)) {
        // 编码器报错,返回上次有效值或报错
        return last_valid_angle;
    }
    
    // 提取位置数据 (bit 12 ~ bit 1)
    uint16_t position = (raw >> 1) & 0x0FFF;
    
    // 换算成角度
    float angle = (float)position / 4096.0f * 360.0f;
    
    last_valid_angle = angle;
    return angle;
}

我曾经踩过的坑:有一款编码器的数据位是MSB对齐的,另一款是LSB对齐的。没仔细看手册,直接移位,结果角度乱跳。后来用逻辑分析仪抓波形,才发现问题。记住:先看数据手册的位定义图,再写代码。

4.4 CRC校验:数据可靠性的最后一道防线

工业现场干扰多,SPI通信偶尔会出错。CRC校验就是用来检测数据有没有被「篡改」的。

很多绝对式编码器会在数据帧末尾附加一个CRC校验码。MCU收到数据后,用同样的多项式算一遍CRC,对比一下。如果一致,数据可信;不一致,扔掉重读。

常见的CRC多项式有:

  • CRC-8:多项式 0x31(x^8 + x^5 + x^4 + 1),常用于短数据帧。
  • CRC-16:多项式 0x8005(x^16 + x^15 + x^2 + 1),用于长数据帧。

我一般用查表法实现CRC,速度快,适合实时控制:

// CRC-8 查表法实现
static const uint8_t crc8_table[256] = {
    0x00, 0x31, 0x62, 0x53, 0xC4, 0xF5, 0xA6, 0x97,
    // ... 省略中间数据,实际使用时需要完整表
};

uint8_t calc_crc8(uint8_t *data, uint8_t len) {
    uint8_t crc = 0x00;
    for (uint8_t i = 0; i < len; i++) {
        crc = crc8_table[crc ^ data[i]];
    }
    return crc;
}

// 使用示例
uint8_t check_encoder_frame(uint16_t raw) {
    uint8_t *bytes = (uint8_t *)&raw;
    uint8_t received_crc = bytes[1] & 0x0F;  // 假设CRC在低4位
    uint8_t calc_crc = calc_crc8(bytes, 1);   // 只对高字节计算
    
    return (received_crc == calc_crc);
}

我的建议:CRC校验虽然好,但别过度依赖。如果连续3次CRC校验失败,我建议你直接报错,而不是一直重试。因为大概率是硬件连接有问题,重试也白搭。

4.5 知识体系总览

下面这张图把绝对式编码器的核心知识点串起来了。你可以把它当作一个「速查地图」:

绝对式编码器知识体系 绝对式编码器知识体系 绝对式编码器 单圈 vs 多圈 单圈:一圈内绝对位置 多圈:圈数 + 单圈位置 SPI通信协议 SCLK / MOSI / MISO / CS 全双工、主机主动发起 数据帧解析 提取位置位 → 换算角度 检查错误/有效标志位 CRC校验 CRC-8 / CRC-16 多项式 查表法实现,速度快 工程应用 FOC换相、零位校准 上电即用,无需回零

这张图把单圈/多圈、SPI通信、数据帧解析、CRC校验和应用串在了一起。你写代码的时候,可以对照这张图,看看自己卡在哪一步。