一、EQEP模块简介

            光电编码器是集光、 机和电技术于一体的数字化传感器, 通过光电转换将输出轴上的机械几何位移量转换成脉冲或者数字量的传感器, 可以高精度测量被测物的转角或直线位量, 是目前应用最多的传感器之一。 它具有分辨率高、 精度高、 结构简单、 体积小、 使用可靠、 性价比高等优点。 在数控机床、 机器人、 雷达、 光电经纬仪、 伺服系统等诸多领域中得到了广泛的应用。 典型的光电编码器主要由码盘、 检测光栅、 光电转换电路(包括光源、 光敏器件、 信号转换电路) 、机械部件等组成, 如下图所示:

DSP TMS320F28335 EQEP模块利用正交解码捕获编码器值_EQEP


            增量式光电编码器的特点是每产生一个输出脉冲信号就对应一个增量位移,但是不能通过输出脉冲区别出在哪个位置上的增量。 它能够产生与位移增量等值的脉冲信号, 其作用是提供一种对连续位移量离散化或增量化以及位移变化(速度) 的传感方法, 它是相对于某个基准点的相对位置增量, 不能直接检测出轴的绝对位置信息。 一般来说, 增量式光电编码器输出 A、 B 两相互差 90 度电度角的脉冲信号(即所谓的两组正交输出信号) , 从而可方便的判断出旋转方向。 同时还有用作参考零位的 Z 相标志(指示) 脉冲信号, 码盘每旋转一周, 只发出一个标志信号。 标志脉冲通过用来指示机械位置或者对积累量清零, 如下图所示:

DSP TMS320F28335 EQEP模块利用正交解码捕获编码器值_DSP_02


            增量式编码器以转动时输出脉冲, 通过计数设备来知道其相对参考点的位置, 当编码器不动或停电时, 依靠计数设备的内部记忆来记住位置。 这样当停电后, 编码器不能有任何的移动, 当来电工作是, 编码器输出脉冲过程中, 也不能有干扰而丢失脉冲, 不然计数设备记忆的零点就会偏移, 而且这种偏移量是无法知道的, 只有错误的生产结果出现后才能知道。 解决的方法是增加参考点, 编码器每经过参考点, 将参考点位置修正进行计数设备的记忆位置。 在参考点以前,是不能保证位置的准确性。 因此, 在工控中就有每次操作前先找参考点, 即开机找零等方法。

            F28335 有两路 eQEP 模块, 每个模块有 4 个管脚, 分别是: QEPA/XCLK、QEPB/XDIR、 eQEPI 和 QPES。 其中前两个引脚被使用在正交时钟模式或者直接计数模式。

(1) 正交时钟模式

正交编码器提供两路相位差为 90 度的脉冲, 相位关系决定了电机旋转方向信息, 脉冲的个数可以决定电机的绝对位置信息。 超前或者顺时钟旋转时, A 路信号超前 B 路信号, 滞后或者逆时针旋转时, B 路信号超前 A 路信号。 正交编码器使用这两路输入引脚可以产生正交时钟和方向信号。

(2) 直接计数模式

在直接计数模式中, 方向和时钟信号直接来自外部, 此时 QEPA 引脚提供时钟输入, QEPB 引脚提供方向输入。后两个引脚 eQEPI 是索引或者起始标记脚, 正交编码器使用索引信号来确定一个绝对的起始位置, 此引脚直接与正交编码器的索引输出端相连, 当此信号到来时, 可以将位置计数器复位清零, 也可以初始化或者锁存位置计数器的值。QEPS 是锁存输入引脚, 锁存引脚输入的主要作用是当规定时间信号到来时,初始或者锁存位置计数器的值, 该引脚通常和传感器或者限制开关连接, 用于通知电机是否达到预定位置。

eQEP 主要包含以下几个功能单元:

–通过 GPIO MUX 寄存器编程锁定 QEPA 或者 QEPB 功能。

–正交解码单元(QDU) 。

–位置计数器和位置计算控制单元(PCCU) 。

–正交边沿捕获单元, 用于低速测量(QCAP) 。

–用于速度/频率测量的时基单元(UTIME) 。

–用于检测的看门狗模块。

QEP 模块内部结构图如下:

DSP TMS320F28335 EQEP模块利用正交解码捕获编码器值_DSP_03


二、代码参考

void encoder_init()
{
EALLOW;
SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK = 1;// 开启GPIO时钟
SysCtrlRegs.PCLKCR1.bit.EQEP1ENCLK = 1; // eQEP1
SysCtrlRegs.PCLKCR1.bit.EQEP2ENCLK = 1; // eQEP2

GpioCtrlRegs.GPBPUD.bit.GPIO50 = 0; // Enable pull-up on GPIO50 (EQEP1A)
GpioCtrlRegs.GPBPUD.bit.GPIO51 = 0; // Enable pull-up on GPIO51 (EQEP1B)

GpioCtrlRegs.GPBQSEL2.bit.GPIO50 = 0; // Sync to SYSCLKOUT GPIO50 (EQEP1A)
GpioCtrlRegs.GPBQSEL2.bit.GPIO51 = 0; // Sync to SYSCLKOUT GPIO51 (EQEP1B)

GpioCtrlRegs.GPBMUX2.bit.GPIO50 = 1; // Configure GPIO50 as EQEP1A
GpioCtrlRegs.GPBMUX2.bit.GPIO51 = 1; // Configure GPIO51 as EQEP1B


GpioCtrlRegs.GPAPUD.bit.GPIO24 = 0; // Enable pull-up on GPIO24 (EQEP2A)
GpioCtrlRegs.GPAPUD.bit.GPIO25 = 0; // Enable pull-up on GPIO25 (EQEP2B)

GpioCtrlRegs.GPAQSEL2.bit.GPIO24 = 0; // Sync to SYSCLKOUT GPIO24 (EQEP2A)
GpioCtrlRegs.GPAQSEL2.bit.GPIO25 = 0; // Sync to SYSCLKOUT GPIO25 (EQEP2B)

GpioCtrlRegs.GPAMUX2.bit.GPIO24 = 2; // Configure GPIO24 as EQEP2A
GpioCtrlRegs.GPAMUX2.bit.GPIO25 = 2; // Configure GPIO25 as EQEP2B

EDIS;
//encoder1
EQep1Regs.QUPRD=1500000; // Unit Timer for 100Hz at 150 MHz SYSCLKOUT


EQep1Regs.QDECCTL.bit.QSRC=00; // QEP quadrature count mode

EQep1Regs.QEPCTL.bit.FREE_SOFT=2;
EQep1Regs.QEPCTL.bit.PCRM=00; // PCRM=00 mode - QPOSCNT reset on index event
EQep1Regs.QEPCTL.bit.UTE=1; // Unit Timeout Enable
EQep1Regs.QEPCTL.bit.QCLM=1; // Latch on unit time out
EQep1Regs.QPOSMAX=0xffffffff;
EQep1Regs.QEPCTL.bit.QPEN=1; // QEP enable

EQep1Regs.QCAPCTL.bit.UPPS=5; // 1/32 for unit position
EQep1Regs.QCAPCTL.bit.CCPS=7; // 1/128 for CAP clock
EQep1Regs.QCAPCTL.bit.CEN=1; // QEP Capture Enable

//encoder2
EQep2Regs.QUPRD=1500000; // Unit Timer for 100Hz at 150 MHz SYSCLKOUT


EQep2Regs.QDECCTL.bit.QSRC=00; // QEP quadrature count mode

EQep2Regs.QEPCTL.bit.FREE_SOFT=2;
EQep2Regs.QEPCTL.bit.PCRM=00; // PCRM=00 mode - QPOSCNT reset on index event
EQep2Regs.QEPCTL.bit.UTE=1; // Unit Timeout Enable
EQep2Regs.QEPCTL.bit.QCLM=1; // Latch on unit time out
EQep2Regs.QPOSMAX=0xffffffff;
EQep2Regs.QEPCTL.bit.QPEN=1; // QEP enable

EQep2Regs.QCAPCTL.bit.UPPS=5; // 1/32 for unit position
EQep2Regs.QCAPCTL.bit.CCPS=7; // 1/128 for CAP clock
EQep2Regs.QCAPCTL.bit.CEN=1; // QEP Capture Enable

}

void get_encoder_val(int16 *leftVal,int16 *rightVal)
{
*leftVal=EQep1Regs.QPOSCNT;
*rightVal=EQep2Regs.QPOSCNT;
EQep1Regs.QPOSCNT=0;//清除值重新开始计数
EQep2Regs.QPOSCNT=0;//清除值重新开始计数
}