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.

[参考译文] TMS320F280049C:eQEP

Guru**** 649970 points
Other Parts Discussed in Thread: C2000WARE, MOTORWARE, SYSCONFIG, TMS320F280049C
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1112991/tms320f280049c-eqep

器件型号:TMS320F280049C
主题中讨论的其他器件:C2000WAREMOTORWARESysConfig

我很难使用 eQEP 模块测量角度和相位。

我看了一些有关 QEP 的 F2837xD 示例、但我无法理解计数周期的定义。 我知道、我们需要定义计数、时钟周期。 positionangle.c 文件通知角度和相位的计算过程、但我在代码中没有看到任何计算。

此外、如果我不想包含(我的 eQEP 计算在 EPWM1中断中、而是在 eQEP 中断上)、那么如何执行它...

我尝试找到很多相关示例、但无法获得任何帮助。

我需要在 F28x4x 系列上实施 SVPWM、因此我需要在这方面提供一些支持。

可以有人在 eQEP 上上传一些示例吗? 还有一些与 SVPWM 或任何适当的 Web 源相关的示例....

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    //
    // 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 v210 $
    // $Release Date: Tue Nov 1 14:46:15 CDT 2016 $
    // $Copyright: Copyright (C) 2013-2016 Texas Instruments Incorporated -
    // http://www.ti.com/ ALL RIGHTS RESERVED $
    //###########################################################################
    
    //
    // 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
    //

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Faiz、

    感谢您的提问!

    我已修改您的回复、以便代码位于"代码"部分。 这会使您的代码更易读、并防止线程难以读取。

    将来、您可以使用以下步骤添加任何代码:
    1.在答复编辑器中,选择"插入"。

    2.选择"代码"

    3.从下拉列表中选择您的编程语言

    4.将代码粘贴到文本框中。

    另请注意、在这些论坛中调试整个代码项目并不常见、我们重点关注器件配置的调试问题、否则。 将来、请不要简单地粘贴完整代码、而是提供可疑问题的特定位置。

    同时,我已指派有关专家回答你的问题。

    此致、

    Vince

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    好的 Vince、

    感谢您的告知

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Faiz、

    您能告诉我您在哪里发布了示例吗? 我们的 C2000Ware SDK 中提供了一些使用 eQEP 外设的示例、您看过这些示例吗? 它们概述了从 eQEP 外设获取计算结果的过程。 关于如何在 eQEP 中断处理程序内执行计算、您需要使用单元计时器。 这显示在 SDK 的 eQEP ex4和 Ex5中。

    此致、

    Peter

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Peter:

    我访问了电机 C2000器件包中的程序、找不到它们在何处定义通道。 所有示例似乎都仅使用 A0。

    我将搜索 C2000 SDK 并告知您。

    谢谢  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Faiz、

    您是指 MotorWare 还是 MotorControl SDK? MotorWare 是我们弃用的 SDK、而 MotorControl SDK 是我们当前支持的电机控制包。

    安装 C2000Ware SDK 后、您可以在以下位置找到示例:

    /driverlib/f28004x/examples/eQEP

    此致、

    Peter

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    是的、我一直在使用电机 c2000ware SDK、但我找不到为 eQEP 定义 GPIO 的位置以及可以更改 GPIO 的位置

    请查找随附的代码

    //#############################################################################
    //
    // FILE:   eqep_ex2_pos_speed.c
    //
    // TITLE:  Position and Speed Measurement Using eQEP
    //
    //! \addtogroup driver_example_list
    //! <h1> Position and Speed Measurement Using eQEP</h1>
    //!
    //! This example provides position and speed measurement using the
    //! capture unit and speed measurement using unit time out of the eQEP module.
    //! ePWM1 and a GPIO are configured to generate simulated eQEP signals. The
    //! ePWM module will interrupt once every period and call the position/speed
    //! calculation function. This example uses the IQMath library to simplify
    //! high-precision calculations.
    //!
    //! In addition to the main example file, the following files must be included
    //! in this project:
    //! - \b eqep_ex2_calculation.c - contains position/speed calculation function
    //! - \b eqep_ex2_calculation.h - includes initialization values for
    //!                               position/speed structure
    //!
    //! The configuration for this example is as follows
    //! - Maximum speed is configured to 6000rpm (baseRPM)
    //! - Minimum speed is assumed at 10rpm for capture pre-scalar selection
    //! - Pole pair is configured to 2 (polePairs)
    //! - Encoder resolution is configured to 4000 counts/revolution (mechScaler)
    //! - Which means: 4000 / 4 = 1000 line/revolution quadrature encoder
    //!   (simulated by ePWM1)
    //! - ePWM1 (simulating QEP encoder signals) is configured for a 5kHz frequency
    //!   or 300 rpm (= 4 * 5000 cnts/sec * 60 sec/min) / 4000 cnts/rev)
    //!
    //! \b SPEEDRPM_FR: High Speed Measurement is obtained by counting the QEP
    //! input pulses for 10ms (unit timer set to 100Hz).
    //!
    //! \b SPEEDRPM_FR = (Position Delta / 10ms) * 60 rpm
    //!
    //! \b SPEEDRPM_PR: Low Speed Measurement is obtained by measuring time period
    //! of QEP edges. Time measurement is averaged over 64 edges for better results
    //! and the capture unit performs the time measurement using pre-scaled SYSCLK.
    //!
    //! Note that the pre-scaler for capture unit clock is selected such that the
    //! capture timer does not overflow at the required minimum frequency. This
    //! example runs indefinitely until the user stops it.
    //!
    //! For more information about the position/speed calculation see the comments
    //! at the beginning of eqep_ex2_calculation.c and the XLS file provided with
    //! the project, eqep_ex2_calculation.xls.
    //!
    //! \b External \b Connections \n
    //! For External connections, Control Card settings are used by default. To use
    //! launchpad pins for output select them in SysConfig.
    //!
    //! - On controlCARD, Connect GPIO6/eQEP1A to GPIO0/ePWM1A 
    //!   (simulates eQEP Phase A signal)
    //! - On controlCARD, Connect GPIO7/eQEP1B to GPIO1/ePWM1B 
    //!   (simulates eQEP Phase B signal)
    //! - On controlCARD, Connect GPIO9/eQEP1I to GPIO4 
    //!   (simulates eQEP Index Signal)
    //! - On LaunchPad, Connect GPIO35/eQEP1A to GPIO10/ePWM6A 
    //!   (simulates eQEP Phase A signal)
    //! - On LaunchPad, Connect GPIO37/eQEP1B to GPIO11/ePWM6B 
    //!   (simulates eQEP Phase B signal)
    //! - On LaunchPad, Connect GPIO59/eQEP1I to GPIO8 
    //!   (simulates eQEP Index Signal)
    //!
    //! \b Watch \b Variables \n
    //!  - \b posSpeed.speedRPMFR - Speed meas. in rpm using QEP position counter
    //!  - \b posSpeed.speedRPMPR - Speed meas. in rpm using capture unit
    //!  - \b posSpeed.thetaMech  - Motor mechanical angle (Q15)
    //!  - \b posSpeed.thetaElec  - Motor electrical angle (Q15)
    //!
    //
    //#############################################################################
    //
    //
    // $Copyright:
    // Copyright (C) 2022 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 "driverlib.h"
    #include "device.h"
    #include "IQmathLib.h"
    #include "eqep_ex2_calculation.h"
    #include "board.h"
    
    
    //
    // Defines
    //
    #define TB_CLK    DEVICE_SYSCLK_FREQ        // Time base clock is SYSCLK
    #define PWM_CLK   5000                      // We want to output at 5 kHz
                                                // (300 rpm)
    #define PRD_VAL   (TB_CLK / (PWM_CLK * 2))  // Calculate value period value
                                                // for up-down count mode
    
    // .9999 / 4000 converted to IQ26 fixed point format
    #define MECH_SCALER     16776
    // 2 pole pairs in this example
    #define POLE_PAIRS      2
    // Angular offset between encoder and Phase A
    #define CAL_ANGLE       0
    // See Equation 5 in eqep_ex2_calculation.c
    #define SPEED_SCALER    ((((uint64_t)32 * DEVICE_SYSCLK_FREQ / 64) * 60) / (24000000))
    // Base/max rpm is 6000rpm
    #define BASE_RPM        6000
    
    
    //
    // Function Prototypes
    //
    void initEPWM(void);
    __interrupt void epwmISR(void);
    
    //
    // Globals
    //
    PosSpeed_Object posSpeed =
    {
        0, 0, 0, 0,     // Initialize outputs to zero
        MECH_SCALER,    // mechScaler
        POLE_PAIRS,     // polePairs
        CAL_ANGLE,      // calAngle
        SPEED_SCALER,   // speedScaler
        0,              // Initialize output to zero
        BASE_RPM,       // baseRPM
        0, 0, 0, 0      // Initialize outputs to zero
    };
    
    uint16_t interruptCount = 0;
    //
    // Main
    //
    void main(void)
    {
        //
        // Initialize device clock and peripherals
        //
        Device_init();
    
        //
        // Disable pin locks and enable internal pullups.
        //
        Device_initGPIO();
    
        //
        // Initialize PIE and clear PIE registers. Disables CPU interrupts.
        //
        Interrupt_initModule();
    
        //
        // Initialize the PIE vector table with pointers to the shell Interrupt
        // Service Routines (ISR).
        //
        Interrupt_initVectorTable();
    
        //
        // Board Initialization
        // Setup eQEP1, configuring the unit timer and quadrature capture units
        // Initialize GPIOs for use as EQEP1A, EQEP1B, and EQEP1I
        //
        Board_init();
    
        //
        // On controlCARD, Initialize GPIO0 to ePWM1A, GPIO1 to ePWM1B, and GPIO4 
        // as an output. (On LaunchPad, use GPIO10 on ePWM6A, GPIO11 on ePWM6B, and 
        // GPIO8 as an output.)
        // They will be used to simulate incoming eQEP Phase A, Phase B, and Index
        // signals respectively.
        //
        GPIO_setPinConfig(DEVICE_GPIO_CFG_EPWMxA);
        GPIO_setPadConfig(DEVICE_GPIO_PIN_EPWMxA, GPIO_PIN_TYPE_STD);
    
        GPIO_setPinConfig(DEVICE_GPIO_CFG_EPWMxB);
        GPIO_setPadConfig(DEVICE_GPIO_PIN_EPWMxB, GPIO_PIN_TYPE_STD);
        
        //
        // Interrupts that are used in this example are re-mapped to ISR functions
        // found within this file.
        //
        Interrupt_register(DEVICE_PERIPHERAL_INT_EPWM, &epwmISR);
    
        //
        // Setup ePWM1 to generate a 5 kHz signal to be an input to the eQEP
        //
        initEPWM();
    
        //
        // Enable interrupts required for this example
        //
        Interrupt_enable(DEVICE_PERIPHERAL_INT_EPWM);
    
        //
        // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
        //
        EINT;
        ERTM;
    
        //
        // Loop indefinitely
        //
        while(1)
        {
            ;
        }
    }
    
    //
    // Function to configure ePWM1 to generate a 5 kHz signal.
    //
    void initEPWM(void)
    {
        //
        // Disable the ePWM time base clock before configuring the module
        //
        SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
        //
        // Set phase shift to 0 and clear the time base counter
        //
        EPWM_setPhaseShift(DEVICE_PERIPHERAL_BASE_EPWM, 0);
        EPWM_setTimeBaseCounter(DEVICE_PERIPHERAL_BASE_EPWM, 0);
    
        //
        // Disable the shadow load; the load will be immediate instead
        //
        EPWM_disableCounterCompareShadowLoadMode(DEVICE_PERIPHERAL_BASE_EPWM,
                                                 EPWM_COUNTER_COMPARE_A);
        EPWM_disableCounterCompareShadowLoadMode(DEVICE_PERIPHERAL_BASE_EPWM,
                                                 EPWM_COUNTER_COMPARE_B);
    
        //
        // Set the compare A value to half the period value, compare B to 0
        //
        EPWM_setCounterCompareValue(DEVICE_PERIPHERAL_BASE_EPWM, 
                                    EPWM_COUNTER_COMPARE_A, PRD_VAL/2);
        EPWM_setCounterCompareValue(DEVICE_PERIPHERAL_BASE_EPWM, 
                                    EPWM_COUNTER_COMPARE_B, 0);
    
        //
        // Set action qualifier behavior on compare A events
        // - EPWM1A --> 1 when CTR = CMPA and increasing
        // - EPWM1A --> 0 when CTR = CMPA and decreasing
        //
        EPWM_setActionQualifierAction(DEVICE_PERIPHERAL_BASE_EPWM, EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_HIGH,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
        EPWM_setActionQualifierAction(DEVICE_PERIPHERAL_BASE_EPWM, EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_LOW,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    
        //
        // Set action qualifier behavior on compare B events
        // - EPWM1B --> 1 when CTR = PRD and increasing
        // - EPWM1B --> 0 when CTR = 0 and decreasing
        //
        EPWM_setActionQualifierAction(DEVICE_PERIPHERAL_BASE_EPWM, EPWM_AQ_OUTPUT_B,
                                      EPWM_AQ_OUTPUT_HIGH,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
        EPWM_setActionQualifierAction(DEVICE_PERIPHERAL_BASE_EPWM, EPWM_AQ_OUTPUT_B,
                                      EPWM_AQ_OUTPUT_LOW,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    
        //
        // Enable interrupt when the counter is equal to PRD
        //
        EPWM_setInterruptSource(DEVICE_PERIPHERAL_BASE_EPWM, EPWM_INT_TBCTR_PERIOD);
        EPWM_enableInterrupt(DEVICE_PERIPHERAL_BASE_EPWM);
    
        //
        // Interrupt on first event
        //
        EPWM_setInterruptEventCount(DEVICE_PERIPHERAL_BASE_EPWM, 1);
    
        //
        // Set the time base clock prescaler to /1
        //
        EPWM_setClockPrescaler(DEVICE_PERIPHERAL_BASE_EPWM, EPWM_CLOCK_DIVIDER_1,
                               EPWM_HSCLOCK_DIVIDER_1);
    
        //
        // Set the period value; don't shadow the register
        //
        EPWM_setPeriodLoadMode(DEVICE_PERIPHERAL_BASE_EPWM, EPWM_PERIOD_DIRECT_LOAD);
        EPWM_setTimeBasePeriod(DEVICE_PERIPHERAL_BASE_EPWM, PRD_VAL);
    
        //
        // Put the time base counter into up-down count mode
        //
        EPWM_setTimeBaseCounterMode(DEVICE_PERIPHERAL_BASE_EPWM,  
                                    EPWM_COUNTER_MODE_UP_DOWN);
    
    
        //
        // Sync the ePWM time base clock
        //
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    }
    
    //
    // ePWM1 ISR--interrupts once every 4 QCLK counts (one period)
    //
     __interrupt void epwmISR(void)
    {
        uint16_t i;
    
        //
        // Position speed and measurement
        //
        PosSpeed_calculate(&posSpeed);
    
    
        //
        // Control loop for position control and speed control
        //
        interruptCount++;
        if(interruptCount == 1000)
        {
            //
            // Pulse index signal (1 pulse/rev)
            //
            GPIO_writePin(DEVICE_GPIO_PIN_IOINDEX, 1);
            for(i = 0; i < 700; i++)
            {
                ;
            }
            GPIO_writePin(DEVICE_GPIO_PIN_IOINDEX, 0);
        }
    
        //
        // Clear interrupt flag and issue ACK
        //
        EPWM_clearEventTriggerInterruptFlag(DEVICE_PERIPHERAL_BASE_EPWM);
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
    }

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Faiz、

    这与 C2000Ware 版本4.01.00.00的示例类似、后者使用我们的 SysConfig GUI 配置 C2000器件的模块。 您可以在 eQEP_ex2_pos_speed.syscfg 文件中找到配置。 有关 SysConfig 的更多信息、请访问: https://training.ti.com/sysconfig-development-tool-c2000-real-time-mcus

    如果您更喜欢 driverlib 实现、则必须使用较旧版本的 C2000Ware、如版本3.04.00.00或更早版本。

    此致、

    Peter

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Peter:

    我将对其进行研究  

    谢谢

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Faiz、

    期待您的回应。 我建议使用示例4和5、因为这些示例是专门为 TMS320F280049C 专用的浮点器件创建的。 Ex1和 ex2从定点器件移植过来、因此必须使用 IQ 数学库、这使得计算更加复杂。  

    此致、

    Peter

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Peter:

    非常感谢您的指导。 我将仔细检查您的建议、如果有任何建议、我将告知您

    谢谢、此致

    Faiz  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我很高兴、Faiz