2、eQEP硬件配置:GPIO引脚分配、eQEP模块时钟使能、输入模式配置

好,咱们正式开始动手配置eQEP。这一节是硬件层面的基础,说白了就是告诉芯片:你要用哪几个引脚、时钟得给这个模块供上、以及你想让编码器信号怎么进来。

我刚开始接触C2000的时候,觉得这部分挺简单的——不就是配几个寄存器嘛。结果有一次板子调了两天,编码器死活读不到正确的脉冲。最后发现是GPIO的输入模式没配对,正交信号被当成普通IO处理了。嗯,从那以后我再也不敢小看这一步了。

2.1 GPIO引脚分配

每个C2000芯片的eQEP模块都有固定的引脚映射。以我常用的TMS320F28069为例,eQEP1的引脚分配是这样的:

eQEP信号 功能描述 GPIO分配 复用功能号
EQEP1A 正交A相 / 方向输入 GPIO20 MUX=1
EQEP1B 正交B相 / 时钟输入 GPIO21 MUX=1
EQEP1I 索引脉冲(Z相) GPIO23 MUX=1
EQEP1S 选通信号(Strobe) GPIO24 MUX=1
个人习惯:我一般会把EQEP1A和EQEP1B放在相邻的GPIO上,这样PCB走线好处理。另外,索引脉冲EQEP1I一定要单独拉一根线,别跟其他信号共用,否则换相定位的时候你会疯掉的。

配置GPIO复用的代码其实很固定。我通常这样写:

// 配置eQEP1的GPIO引脚
// GPIO20 -> EQEP1A
GPIO_setPinConfig(GPIO_20_EQEP1A);
GPIO_setDirectionMode(20, GPIO_DIR_MODE_IN);
GPIO_setPadConfig(20, GPIO_PIN_TYPE_PULLUP);

// GPIO21 -> EQEP1B
GPIO_setPinConfig(GPIO_21_EQEP1B);
GPIO_setDirectionMode(21, GPIO_DIR_MODE_IN);
GPIO_setPadConfig(21, GPIO_PIN_TYPE_PULLUP);

// GPIO23 -> EQEP1I (索引)
GPIO_setPinConfig(GPIO_23_EQEP1I);
GPIO_setDirectionMode(23, GPIO_DIR_MODE_IN);
GPIO_setPadConfig(23, GPIO_PIN_TYPE_PULLUP);

这里有个细节:上拉电阻一定要使能。编码器是开漏输出,你不配上拉,信号浮空的时候会乱跳。我在项目里见过有人没配上拉,结果电机静止的时候位置计数器还在跑——那画面太美我不敢看。

2.2 eQEP模块时钟使能

GPIO配好了,但模块本身还没通电呢。C2000的外设时钟默认是关闭的,你得手动打开。

时钟使能分两步走:

  1. 系统级时钟使能:通过PCLKCR寄存器打开eQEP模块的时钟
  2. 模块级复位释放:让eQEP模块从复位状态进入正常工作模式

代码实现很简单:

// 1. 使能eQEP1模块时钟
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EQEP1);

// 2. 释放模块复位
SysCtl_resetPeripheral(SYSCTL_PERIPH_CLK_EQEP1);
DELAY_US(10);  // 等时钟稳定,我习惯加个小延时
我曾经踩过的坑:时钟使能之后直接就去配eQEP寄存器,结果写进去的值读回来全是0。后来查手册才发现,模块复位释放之后需要等几个时钟周期才能访问寄存器。加个10微秒的延时,问题就解决了。

你想想看,时钟都没供上,你写寄存器有什么用?所以这个顺序千万别搞反——先开时钟,再释放复位,最后才能配寄存器。

2.3 输入模式配置

这是最核心的部分。eQEP支持三种输入模式,你得根据编码器类型来选。

模式 适用场景 信号定义 计数方式
正交模式 增量式编码器(A/B相) EQEP1A = A相, EQEP1B = B相 4倍频计数,方向由相位差决定
方向/计数模式 单端脉冲编码器 / 霍尔传感器 EQEP1A = 脉冲, EQEP1B = 方向 每个脉冲计1次,方向由电平决定
向上/向下计数模式 双脉冲编码器 EQEP1A = 正向脉冲, EQEP1B = 反向脉冲 各自独立计数,内部做加减

我个人最常用的是正交模式。为什么呢?因为正交信号自带方向信息,而且4倍频之后分辨率直接翻4倍。举个例子,一个2500线的编码器,正交模式下你能得到10000个计数/圈——这对低速换相来说太重要了。

配置正交模式的代码:

// 设置eQEP为正交计数模式
EQEP_setDecoderConfig(EQEP1_BASE, 
    EQEP_DECODER_QUADRATURE_COUNT |
    EQEP_DECODER_INPUT_NORMAL_POLARITY |
    EQEP_DECODER_SWAP_INPUTS_DISABLE);

// 配置计数方向:正向计数
EQEP_setDirectionConfig(EQEP1_BASE, EQEP_DIR_COUNT_UP);

// 设置位置计数器初始值
EQEP_setPosition(EQEP1_BASE, 0);

这里有个参数值得注意——SWAP_INPUTS。如果你发现电机正转的时候位置计数器在减小,别急着改代码,先试试把这个位使能。说白了就是把A/B相交换一下,相当于在软件层面调换两根线的顺序。

核心要点:
  • 正交模式:A/B相差90°,硬件自动判向,4倍频计数
  • 方向/计数模式:A相给脉冲,B相给方向电平
  • 向上/向下计数模式:两路独立脉冲,内部做加减
  • 索引脉冲(Z相)在所有模式下都可用,用于圈数校准

如果你用的是方向/计数模式,配置会稍有不同:

// 方向/计数模式配置
EQEP_setDecoderConfig(EQEP1_BASE,
    EQEP_DECODER_DIRECTION_COUNT |
    EQEP_DECODER_INPUT_NORMAL_POLARITY);

// 设置方向引脚有效电平
EQEP_setDirectionConfig(EQEP1_BASE, EQEP_DIR_COUNT_UP);

嗯,这里要注意:方向/计数模式下,B相的电平决定了计数方向。高电平正向还是低电平正向?这个得看你的编码器手册。我一般会在初始化之后手动转一下电机,看看计数值对不对,不对就改极性。

最后,我把整个配置流程画成了一张图,方便你对照检查:

eQEP硬件配置流程图 步骤1:GPIO引脚分配 配置复用功能 → 方向输入 → 使能上拉 步骤2:模块时钟使能 PCLKCR使能 → 释放复位 → 延时等待 步骤3:选择输入模式 正交 / 方向计数 / 向上向下 正交模式 4倍频 · 自动判向 方向/计数模式 脉冲+方向电平 向上/向下模式 双脉冲独立计数 ✅ eQEP硬件配置完成 位置计数器已初始化,等待编码器信号

这张图把整个流程串起来了。你照着这个顺序走,一般不会出问题。如果调试的时候发现位置读数不对,回头检查一下:GPIO复用配对了没?时钟使能了没?模式选对了没?