This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

有没有eqep操作软件的代码例子,

Other Parts Discussed in Thread: C2000WARE

想要测量编码器的A相和B相,如何用eqep测量编码器电机的位置和速度,应该设置哪些参数。

  • 不知您现在使用的是哪款芯片?您可以在C2000WARE内查找相关的例程,如下

    C:\ti\c2000\C2000Ware_2_00_00_02\device_support\f2837xd\examples\cpu1\eqep_pos_speed\cpu01

    //###########################################################################
    //
    // FILE:    Example_posspeed.c
    //
    // TITLE:   Pos/speed measurement using EQEP peripheral
    //
    // DESCRIPTION:
    //
    // This file includes the EQEP initialization and position and speed
    // calculation functions called by Eqep_posspeed.c.  The position and speed
    // calculation steps performed by POSSPEED_Calc() at  SYSCLKOUT =  200 MHz are
    // described below:
    //
    // 1. This program calculates: **theta_mech**
    //
    //    theta_mech = QPOSCNT/mech_Scaler = QPOSCNT/4000, where 4000 is the number
    //                 of counts in 1 revolution.
    //                (4000/4 = 1000 line/rev. quadrature encoder)
    //
    // 2. This program calculates: **theta_elec**
    //
    //    theta_elec = (# pole pairs) * theta_mech = 2*QPOSCNT/4000
    //
    // 3. This program calculates: **SpeedRpm_fr**
    //
    //    SpeedRpm_fr = [(x2-x1)/4000]/T   - Equation 1
    //    Note (x2-x1) = difference in number of QPOSCNT counts. Dividing (x2-x1)
    //    by 4000 gives position relative to Index in one revolution.
    // If base RPM  = 6000 rpm:   6000 rpm = [(x2-x1)/4000]/10ms   - Equation 2
    //                                     = [(x2-x1)/4000]/(.01s*1 min/60 sec)
    //                                     = [(x2-x1)/4000]/(1/6000) min
    //                         max (x2-x1) = 4000 counts, or 1 revolution in 10 ms
    //
    //
    // If both sides of Equation 2 are divided by 6000 rpm, then:
    //                   1 = [(x2-x1)/4000] rev./[(1/6000) min * 6000rpm]
    //                   Because (x2-x1) must be <4000 (max) for QPOSCNT increment,
    //                   (x2-x1)/4000 < 1 for CW rotation
    //                   And because (x2-x1) must be >-4000 for QPOSCNT decrement,
    //                   (x2-x1)/4000>-1  for CCW rotation
    //                   speed_fr = [(x2-x1)/4000]/[(1/6000) min * 6000rpm]
    //                            = (x2-x1)/4000   - Equation 3
    //
    // To convert speed_fr to RPM, multiply Equation 3 by 6000 rpm
    //                   SpeedRpm_fr = 6000rpm *(x2-x1)/4000  - Final Equation
    //
    // 2. **min rpm ** = selected at 10 rpm based on CCPS prescaler options
    //    available (128 is greatest)
    //
    // 3. **SpeedRpm_pr**
    //    SpeedRpm_pr = X/(t2-t1)  - Equation 4
    //    where X = QCAPCTL [UPPS]/4000 rev. (position relative to Index in
    //                                        1 revolution)
    // If  max/base speed = 6000 rpm:
    //               6000 = (32/4000)/[(t2-t1)/(200MHz/64)]
    //           where 32 = QCAPCTL [UPPS] (Unit timeout - once every 32 edges)
    //            32/4000 = position in 1 revolution (position as a fraction
    //                                                of 1 revolution)
    //   t2-t1/(200MHz/64), t2-t1= # of QCAPCLK cycles, and
    //      QCAPCLK cycle = 1/(200MHz/64)
    //                    = QCPRDLAT
    //
    // So:       6000 rpm = [32(200MHz/64)*60s/min]/[4000(t2-t1)]
    //              t2-t1 = [32(200MHz/64)*60s/min]/(4000*6000rpm)  - Equation 5
    //                    = 250 CAPCLK cycles = maximum (t2-t1) = SpeedScaler
    //
    // Divide both sides by (t2-t1), and:
    //            1 = 32/(t2-t1) = [32(200MHz/64)*60 s/min]/(4000*6000rpm)]/(t2-t1)
    //       Because (t2-t1) must be < 250 for QPOSCNT increment:
    //               250/(t2-t1) < 1 for CW rotation
    //       And because (t2-t1) must be >-250 for QPOSCNT decrement:
    //                250/(t2-t1)> -1 for CCW rotation
    //
    //       eed_pr = 250/(t2-t1)
    //             or [32(200MHz/64)*60 s/min]/(4000*6000rpm)]/(t2-t1) - Equation 6
    //
    // To convert speed_pr to RPM:
    // Multiply Equation 6 by 6000rpm:
    // SpeedRpm_fr  = 6000rpm * [32(200MHz/64)*60 s/min]/[4000*6000rpm*(t2-t1)]
    //              = [32(200MHz/64)*60 s/min]/[4000*(t2-t1)]
    //              or [(32/4000)rev * 60 s/min]/[(t2-t1)(QCPRDLAT)]-Final Equation
    //
    // More detailed calculation results can be found in the Example_freqcal.xls
    // spreadsheet included in the example folder.
    //
    // This file contains source for the posspeed module
    //
    //###########################################################################
    // $TI Release: F2837xD Support Library v3.06.00.00 $
    // $Release Date: Mon May 27 06:48:24 CDT 2019 $
    // $Copyright:
    // Copyright (C) 2013-2019 Texas Instruments Incorporated - http://www.ti.com/
    //
    // Redistribution and use in source and binary forms, with or without 
    // modification, are permitted provided that the following conditions 
    // are met:
    // 
    //   Redistributions of source code must retain the above copyright 
    //   notice, this list of conditions and the following disclaimer.
    // 
    //   Redistributions in binary form must reproduce the above copyright
    //   notice, this list of conditions and the following disclaimer in the 
    //   documentation and/or other materials provided with the   
    //   distribution.
    // 
    //   Neither the name of Texas Instruments Incorporated nor the names of
    //   its contributors may be used to endorse or promote products derived
    //   from this software without specific prior written permission.
    // 
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    // $
    //###########################################################################
    
    //
    // 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 = 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 = 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
    
        //
        // 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
        }
    
        //
        // High Speed Calculation using QEP Position counter
        //
        // Check unit Time out-event for speed calculation:
        // Unit Timer is configured for 100Hz in INIT function
        //
        if(EQep1Regs.QFLG.bit.UTO == 1)    // If unit timeout (one 100Hz period)
        {
            //
            // Differentiator
            //
            // The following lines calculate
            // position = (x2-x1)/4000 (position in 1 revolution)
            //
            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
                }
            }
    
            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)               // Unit position event
        {
            if(EQep1Regs.QEPSTS.bit.COEF == 0)             // No Capture overflow
            {
                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;
            }
    
            //
            // Convert 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
        }
    }
    
    //
    // End of file
    //
    

  • 这个我觉得你先弄清楚原理会比较好理解代码 要想测出电机转的方向 就要将A B相都接入
    如果A超前B 90度是正向 那么B超前A就是反向
    只测速度的话 A或B接入CAP管脚 配置一个通用定时器 两个沿触记录两次定时器的值 然后通过
    差值计算出频率
    位置可能需要Z相配合