TMS320F28377S: About eQEP routines are unable to get location values after migration

Part Number: TMS320F28377S

At present, I plan to use the eQEP routine to implement it on TI's 28377s development board, and connect it to the TTL encoder instead of simulating the AB phase of the ePWM input encoder in the routine. In addition, there is no need for Z-phase signal (zero position), only the position and speed of the motor need to be obtained through the AB phase of the encoder.
But now, I have connected the AB signal of the encoder to the corresponding GPIO port (76, 75) in the routine, and the program has not reported any errors. After burning it onto the board, QPOSCNT remains 0, and there is a signal change in the GPIO port corresponding to rotating the encoder, but the position value has not changed.

and The GPIO settings are as follows(InitEQep1Gpio(void)):

void InitEQep1Gpio(void)
{
    EALLOW;
    GpioCtrlRegs.GPCPUD.bit.GPIO76 = 1;
    GpioCtrlRegs.GPCPUD.bit.GPIO75 = 1;
    
    GpioCtrlRegs.GPCDIR.bit.GPIO76 = 0;
    GpioCtrlRegs.GPCDIR.bit.GPIO75 = 0;
    
    GpioCtrlRegs.GPCQSEL1.bit.GPIO76 = 0;
    GpioCtrlRegs.GPCQSEL1.bit.GPIO75 = 0;
    
    GpioCtrlRegs.GPCMUX1.bit.GPIO76 = 1;
    GpioCtrlRegs.GPCMUX1.bit.GPIO75 = 1;
}

Eqep_pos_speed.c:


#include "F28x_Project.h"
#include "Example_posspeed.h"


POSSPEED qep_posspeed=POSSPEED_DEFAULTS;




//
// Main
//
void main(void)
{
//
// 第 1 步。初始化系统控制:
// PLL、看门狗、启用外设时钟

   InitSysCtrl();

//
// 第 2 步。初始化 GPIO:
// 该示例函数位于 F2837xS_Gpio.c 文件中,用于 
// 说明如何设置 GPIO 的默认状态。

   InitEQep1Gpio();

//
// 第 3 步。清除所有__中断并初始化 PIE 向量表:
// 禁用 CPU__中断
//
   DINT;

//
// 将 PIE 控制寄存器初始化为默认状态
// 默认状态是所有 PIE 中断被禁用,标志被清除
// 该函数位于 F2837xS_PieCtrl.c 文件中
//
   InitPieCtrl();


   IER = 0x0000;
   IFR = 0x0000;


   InitPieVectTable();

//
// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
//
//   EALLOW;  // This is needed to write to EALLOW protected registers
   // PieVectTable.EQEP1_INT= &prdTick;
//   EDIS;    // This is needed to disable write to EALLOW protected registers

//
// 第 4 步。初始化所有设备外设:
//
   // initEpwm();  // This function exists in Example_EPwmSetup.c

//
// 第 5 步。用户专用代码,启用__中断:
// 启用与 CPU-Timer 0 相连的 CPU INT1:
//
// IER |= M_INT5;

//
// Enable TINT0 in the PIE: Group 3 __interrupt 1
//
// PieCtrlRegs.PIEIER5.bit.INTx1 = 1;

//
// Enable global Interrupts and higher priority real-time debug events:
//



   EINT;   // Enable Global __interrupt INTM
   ERTM;   // Enable Global realtime __interrupt DBGM

   qep_posspeed.init(&qep_posspeed);

   for(;;)
   {
      qep_posspeed.calc(&qep_posspeed);
   }
}










Example_pos_speed.c:

//
// Included Files
//
#include "F28x_Project.h"
#include "Example_posspeed.h"

//
// POSSPEED_Init - Initialize EQEP1 configuration
//
void  POSSPEED_Init(void)
{
    EQep1Regs.QUPRD = 2000000;            // Unit Timer for 100Hz at 200 MHz
                                          // SYSCLKOUT
    EQep1Regs.QDECCTL.bit.QSRC = 00;      // QEP quadrature count mode
    EQep1Regs.QEPCTL.bit.FREE_SOFT = 2;
    EQep1Regs.QEPCTL.bit.PCRM = 01;       
    EQep1Regs.QEPCTL.bit.UTE = 1;         // Unit Timeout Enable
    EQep1Regs.QEPCTL.bit.QCLM = 1;        // Latch on unit time out
    EQep1Regs.QPOSMAX = 0x270f;
    EQep1Regs.QEPCTL.bit.QPEN = 1;        // QEP enable
    EQep1Regs.QCAPCTL.bit.UPPS = 5;       // 1/32 for unit position
    EQep1Regs.QCAPCTL.bit.CCPS = 6;       // 1/64 for CAP clock
    EQep1Regs.QCAPCTL.bit.CEN = 1;        // QEP Capture Enable
}

//
// POSSPEED_Calc - Perform the position calculations
//
void POSSPEED_Calc(POSSPEED *p)
{
    long tmp;
    unsigned int pos16bval,temp1;
    _iq Tmp1,newp,oldp;

    //
    // Position calculation - mechanical and electrical motor angle
    //
    p->DirectionQep = EQep1Regs.QEPSTS.bit.QDF;  // Motor direction:
                                                 // 0=CCW/reverse, 1=CW/forward

    pos16bval = (unsigned int)EQep1Regs.QPOSCNT; // capture position once per QA/QB period
    p->theta_raw = pos16bval+ p->cal_angle;      // raw theta = current pos. + ang.offset from QA   定时器2的初始位置=当前位置+偏置值

    //
    // The following lines calculate
    // p->theta_mech ~= QPOSCNT/mech_scaler [current cnt/(total cnt in 1 rev.)]
    // where mech_scaler = 4000 cnts/revolution
    //
    tmp = (long)((long)p->theta_raw*(long)p->mech_scaler);   // Q0*Q26 = Q26
    tmp &= 0x03FFF000;
    p->theta_mech = (int)(tmp>>11);                          // Q26 -> Q15
    p->theta_mech &= 0x7FFF;

    //
    // The following lines calculate p->elec_mech
    //
    p->theta_elec = p->pole_pairs*p->theta_mech;             // Q0*Q15 = Q15    电气角=极对数*当前的机械角
    p->theta_elec &= 0x7FFF;                                 //位与    清除符号位->非负

    //
    // Check an index occurrence
    //
    if(EQep1Regs.QFLG.bit.IEL == 1)
    {
       p->index_sync_flag = 0x00F0;
       EQep1Regs.QCLR.bit.IEL = 1;    // Clear __interrupt flag
    }

    // 高速
    // 使用 QEP 位置计数器进行计算
    // 检查用于速度计算的单位超时事件:
    // 在 INIT 功能中,单位定时器被配置为 100Hz
    //
    if(EQep1Regs.QFLG.bit.UTO == 1)    // If unit timeout (one 100Hz period)
    {
        //
        // Differentiator
        //
        // The following lines calculate
        // 位置 = (x2-x1)/4000(转一圈的位置)
        //
        pos16bval = (unsigned int)EQep1Regs.QPOSLAT;   // Latched POSCNT value
        tmp = (long)((long)pos16bval*(long)p->mech_scaler); // Q0*Q26 = Q26
        tmp &= 0x03FFF000;
        tmp = (int)(tmp>>11);                               // Q26 -> Q15
        tmp &= 0x7FFF;
        newp = _IQ15toIQ(tmp);
        oldp = p->oldpos;

        if(p->DirectionQep==0)                     // POSCNT is counting down
        {
            if(newp>oldp)
            {
                Tmp1 = - (_IQ(1) - newp + oldp);    // x2-x1 should be negative     ->可能是由于位置计数器溢出
            }
            else
            {
                Tmp1 = newp -oldp;
            }
        }
        else if(p->DirectionQep == 1)              // POSCNT is counting up
        {
            if(newp<oldp)
            {
                Tmp1 = _IQ(1) + newp - oldp;
            }
            else
            {
                Tmp1 = newp - oldp;                 // x2-x1 should be positive
            }
        }



//      如果计算出的位置差 Tmp1 大于 _IQ(1)(即大于1的定点数表示),则将速度 p->Speed_fr 设置为 _IQ(1)。这可能是为了避免速度值过高或处理异常情况
//      如果 Tmp1 小于 _IQ(-1)(即小于-1的定点数表示),则将速度 p->Speed_fr 设置为 _IQ(-1)。这同样是为了处理速度值过低或异常情况
//      else: 在其他情况下,直接将 Tmp1 的值赋给 p->Speed_fr,表示电机的实际速度

        if(Tmp1>_IQ(1))
        {
            p->Speed_fr = _IQ(1);
        }
        else if(Tmp1<_IQ(-1))
        {
            p->Speed_fr = _IQ(-1);
        }
        else
        {
            p->Speed_fr = Tmp1;
        }

        //
        // Update the electrical angle
        //
        p->oldpos = newp;

        //
        // Change motor speed from pu value to rpm value (Q15 -> Q0)
        // Q0 = Q0*GLOBAL_Q => _IQXmpy(), X = GLOBAL_Q
        //
        p->SpeedRpm_fr = _IQmpy(p->BaseRpm,p->Speed_fr);

        EQep1Regs.QCLR.bit.UTO=1;                   // Clear __interrupt flag
    }

    //低速
    // Low-speed computation using QEP capture counter
    //
    if(EQep1Regs.QEPSTS.bit.UPEVNT == 1)               //当检测到单位位置事件(UPEVNT)时,代表着编码器已经移动了位置
    {
        if(EQep1Regs.QEPSTS.bit.COEF == 0)             // 检查捕获计数器是否溢出
        {
            temp1 = (unsigned long)EQep1Regs.QCPRDLAT; // temp1 = t2-t1
        }
        else   // Capture overflow, saturate the result
        {
            temp1 = 0xFFFF;
        }

        //
        // 计算 p->Speed_pr = p->SpeedScaler/temp1
        //
        p->Speed_pr = _IQdiv(p->SpeedScaler,temp1);
        Tmp1 = p->Speed_pr;


        // 速度限制 
        if (Tmp1>_IQ(1))
        {
            p->Speed_pr = _IQ(1);
        }
        else
        {
            p->Speed_pr = Tmp1;
        }

        //
        // 转换为RPM(每分钟转数)   p->Speed_pr to RPM
        //
        if(p->DirectionQep == 0)  // Reverse direction = negative
        {
            //
            // Q0 = Q0*GLOBAL_Q => _IQXmpy(), X = GLOBAL_Q
            //
            p->SpeedRpm_pr = -_IQmpy(p->BaseRpm,p->Speed_pr);
        }
        else                     // Forward direction = positive
        {
            //
            // Q0 = Q0*GLOBAL_Q => _IQXmpy(), X = GLOBAL_Q
            //
            p->SpeedRpm_pr = _IQmpy(p->BaseRpm,p->Speed_pr);
        }

        EQep1Regs.QEPSTS.all = 0x88; // Clear Unit position event flag
                                     // Clear overflow error flag
    }
}