3. 正交编码器接口与转速计算

任务目标

本案例实现基于C2000系列DSP(以TMS320F280049C为例)的eQEP模块配置,完成对正交编码器信号的解码,并计算电机转子位置与转速。核心内容包括:eQEP引脚初始化、位置计数器配置、单位时间位置差计算转速,以及通过串口输出结果供验证。

硬件连接与依赖

  • 编码器A/B信号分别连接至EQEP1A(GPIO24)和EQEP1B(GPIO25),索引信号Z(GPIO26)可选接入。
  • 依赖driverlib库(C2000Ware),需在工程中包含eqep.h、gpio.h、sysctl.h、uart.h头文件。
  • 编码器线数(PPR)需根据实际硬件修改宏ENCODER_PPR。

核心实现

#include "driverlib.h"
#include "device.h"

#define ENCODER_PPR    1000    // 编码器每圈脉冲数
#define SPEED_CALC_MS  100     // 转速计算周期(ms)

volatile uint32_t g_position = 0;
volatile int32_t  g_speed_rpm = 0;
volatile uint32_t g_last_pos = 0;

// 初始化eQEP1为正交计数模式
void EQEP1_Init(void)
{
    // 启用eQEP1时钟
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EQEP1);

    // 配置GPIO24/25为EQEP1A/1B功能
    GPIO_setPinConfig(GPIO_24_EQEP1A);
    GPIO_setPinConfig(GPIO_25_EQEP1B);
    GPIO_setDirectionMode(24, GPIO_DIR_MODE_IN);
    GPIO_setDirectionMode(25, GPIO_DIR_MODE_IN);
    GPIO_setQualificationMode(24, GPIO_QUAL_ASYNC);
    GPIO_setQualificationMode(25, GPIO_QUAL_ASYNC);

    // 配置eQEP模块
    EQEP_setDecoderConfig(EQEP1_BASE,
        EQEP_CONFIG_2X_RESOLUTION |        // 2倍频(A/B边沿计数)
        EQEP_CONFIG_QUADRATURE_MODE);       // 正交计数模式

    EQEP_setPositionCounterConfig(EQEP1_BASE,
        EQEP_POSITION_RESET_IDX,            // 索引信号复位
        0xFFFFFFFF);                        // 最大计数

    EQEP_setPositionCounter(EQEP1_BASE, 0);
    EQEP_setLatchMode(EQEP1_BASE, EQEP_LATCH_WINDOW_ENABLE);
    EQEP_setCaptureLatchMode(EQEP1_BASE, EQEP_CAPTURE_CLOCK_DIV_1);
}

// 读取当前位置(带方向)
uint32_t EQEP1_GetPosition(void)
{
    return EQEP_getPositionCounter(EQEP1_BASE);
}

// 定时计算转速(在定时器中断中调用,周期100ms)
void Speed_Calculate(void)
{
    uint32_t cur_pos = EQEP1_GetPosition();
    int32_t delta = (int32_t)(cur_pos - g_last_pos);
    g_last_pos = cur_pos;
    g_position = cur_pos;

    // 转速 = 脉冲差 / (PPR*2) / 时间(分钟)
    // 时间 = SPEED_CALC_MS/1000/60 分钟
    float rev = (float)delta / (ENCODER_PPR * 2);
    float minutes = (float)SPEED_CALC_MS / 60000.0f;
    g_speed_rpm = (int32_t)(rev / minutes);
}

void main(void)
{
    Device_init();
    EQEP1_Init();

    // 配置定时器0,周期100ms触发中断
    CPUTimer_setPeriod(CPUTIMER0_BASE, 100000);
    CPUTimer_registerInterrupt(CPUTIMER0_BASE, &Speed_Calculate);
    CPUTimer_enableInterrupt(CPUTIMER0_BASE);
    CPUTimer_startTimer(CPUTIMER0_BASE);

    // 串口初始化(用于输出结果)
    UART_init(UART0_BASE, 9600);

    while(1)
    {
        // 主循环中可通过调试器观察g_position和g_speed_rpm
        DEVICE_DELAY_US(500000);
    }
}

运行与验证

  1. 将代码烧录至F280049C LaunchPad,编码器A/B接入GPIO24/25。
  2. 在CCS调试模式下,将g_position和g_speed_rpm添加至Expressions窗口。
  3. 手动旋转编码器轴:g_position应随旋转方向递增或递减;g_speed_rpm应显示当前转速(正负代表方向)。
  4. 通过标准:以恒定速度旋转编码器,观察g_speed_rpm数值稳定且与实测转速(如用手持转速表)误差在±5%以内;反向旋转时数值符号翻转。

关键说明

  • 本代码使用2倍频模式,因此每圈计数值为PPR×2。若编码器为1000线,则每圈2000个计数。
  • 转速计算周期SPEED_CALC_MS需与定时器中断周期一致(本例100ms),修改时需同步调整。
  • 索引信号Z未强制使用,若需精确定位可接入GPIO26并配置EQEP_POSITION_RESET_IDX为索引复位模式。
  • 实际工程中建议增加速度低通滤波,但本案例为演示最小实现,未包含滤波逻辑。