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 |
配置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的外设时钟默认是关闭的,你得手动打开。
时钟使能分两步走:
- 系统级时钟使能:通过PCLKCR寄存器打开eQEP模块的时钟
- 模块级复位释放:让eQEP模块从复位状态进入正常工作模式
代码实现很简单:
// 1. 使能eQEP1模块时钟
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EQEP1);
// 2. 释放模块复位
SysCtl_resetPeripheral(SYSCTL_PERIPH_CLK_EQEP1);
DELAY_US(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相的电平决定了计数方向。高电平正向还是低电平正向?这个得看你的编码器手册。我一般会在初始化之后手动转一下电机,看看计数值对不对,不对就改极性。
最后,我把整个配置流程画成了一张图,方便你对照检查:
这张图把整个流程串起来了。你照着这个顺序走,一般不会出问题。如果调试的时候发现位置读数不对,回头检查一下:GPIO复用配对了没?时钟使能了没?模式选对了没?