4. EQEP接口读取增量式编码器位置

EQEP 与增量式编码器的信号连接

增量式编码器输出 A、B 两路正交方波和一路每转一次的 Index(Z)脉冲。C2000 的 EQEP 模块通过 QEPA/QEPB 引脚接收正交信号,通过 QEPI 引脚接收 Index 信号,内部四倍频计数并自动判别方向。以 2500 线编码器为例,四倍频后每转计数为 10000,机械角度分辨率为 0.036°。

增量式编码器 2500 线 / 转 A / B / Z 输出 A+ A- B+ B- Z+ Z- 差分或单端 QEPA QEPB QEPI C2000 EQEP 模块 正交解码器 (4× 倍频) 位置计数器 QPOSCNT 方向 / 位置比较单元 QPOSCNT 计数值 QEPSTS 方向位 QPOSILAT 零位锁存 关键参数与计算关系 • 四倍频计数:QPOSCNT 每转变化 = 2500 × 4 = 10000 • 机械角度:θ = (QPOSCNT / 10000) × 360° • 方向判断:QEPSTS[QDF] = 0 正转,= 1 反转 • 零位锁存:Index 脉冲触发 QPOSILAT 记录当前计数值 A/B 相位差 90° → 硬件自动判向

EQEP 初始化配置

以下代码完成 EQEP1 的基本配置:正交计数模式、四倍频、Index 事件锁存、单位定时器用于测速。配置前需将对应 GPIO 复用为 EQEP 功能。

#include "F28x_Project.h"

void EQEP1_Init(void)
{
    // 1. GPIO 复用配置:GPIO20=A, GPIO21=B, GPIO23=Index
    EALLOW;
    GpioCtrlRegs.GPAMUX2.bit.GPIO20 = 1;  // EQEP1A
    GpioCtrlRegs.GPAMUX2.bit.GPIO21 = 1;  // EQEP1B
    GpioCtrlRegs.GPAMUX2.bit.GPIO23 = 1;  // EQEP1I
    GpioCtrlRegs.GPAQSEL2.bit.GPIO20 = 0; // 同步到 SYSCLKOUT
    GpioCtrlRegs.GPAQSEL2.bit.GPIO21 = 0;
    GpioCtrlRegs.GPAQSEL2.bit.GPIO23 = 0;
    EDIS;

    // 2. EQEP 解码控制:正交计数,4 倍频
    EQep1Regs.QDECCTL.bit.QSRC = 0;    // 正交计数模式
    EQep1Regs.QDECCTL.bit.QAP  = 0;    // QEPA 不反相
    EQep1Regs.QDECCTL.bit.QBP  = 0;    // QEPB 不反相
    EQep1Regs.QDECCTL.bit.XCR  = 0;    // 4 倍频(A/B 双边沿)

    // 3. 位置计数器:清零并允许
    EQep1Regs.QPOSCNT = 0;
    EQep1Regs.QPOSMAX = 9999;           // 2500 线 × 4 - 1

    // 4. Index 事件:上升沿锁存位置
    EQep1Regs.QEPCTL.bit.IEI = 2;      // Index 上升沿
    EQep1Regs.QEPCTL.bit.IEL = 1;      // 使能 Index 锁存
    EQep1Regs.QEPCTL.bit.QPEN = 1;     // 使能位置计数器

    // 5. 单位定时器:用于低速测速(可选)
    EQep1Regs.QUPRD = 60000000;         // 60 MHz 下 1 秒
    EQep1Regs.QEPCTL.bit.UTE = 1;       // 使能单位定时器
    EQep1Regs.QEPCTL.bit.UPEVNT = 1;    // 单位位置事件
}

读取机械角度与方向

通过读取 QPOSCNT 计算机械角度,通过 QEPSTS 的 QDF 位判断旋转方向。Index 锁存值 QPOSILAT 可用于零位对齐。

#define ENCODER_LINES   2500
#define COUNTS_PER_REV  (ENCODER_LINES * 4)   // 10000

float EQEP1_GetMechAngle(void)
{
    int32_t cnt = (int32_t)EQep1Regs.QPOSCNT;
    if (cnt < 0) cnt += COUNTS_PER_REV;       // 处理反转回绕
    return (float)cnt * 360.0f / (float)COUNTS_PER_REV;
}

int16_t EQEP1_GetDirection(void)
{
    // QDF: 0 = 正转(QPOSCNT 递增),1 = 反转
    return (EQep1Regs.QEPSTS.bit.QDF == 0) ? 1 : -1;
}

int32_t EQEP1_GetIndexLatch(void)
{
    return (int32_t)EQep1Regs.QPOSILAT;       // Index 脉冲时的计数值
}

正反转与零位验证

手动旋转编码器轴,通过串口或 CCS Expressions 观察以下现象:

  • 正转:QPOSCNT 从 0 递增至 9999 后回绕,QDF = 0,机械角度从 0° 增至 360°。
  • 反转:QPOSCNT 从 0 递减至 9999(下溢回绕),QDF = 1,机械角度从 360° 降至 0°。
  • 零位:每转一圈 Index 脉冲触发一次,QPOSILAT 应稳定在 0 附近(若安装对齐良好)。
若 QPOSILAT 每次锁存值波动较大,说明编码器 Index 与机械零位未对齐,可通过调整编码器安装角度或在软件中记录偏移量进行补偿。若 QDF 方向与预期相反,交换 QEPA 与 QEPB 接线即可。
EQEP 引脚为 3.3V 电平,若编码器输出为 5V 差分信号(如 RS-422),必须经过电平转换或差分接收器(如 AM26LS32)后再接入 C2000,否则可能损坏 GPIO。