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.

[参考译文] TMS320F28388D:eQEP 中断只运行一次、然后停止运行

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1123042/tms320f28388d-the-interrupt-for-eqep-only-runs-once-then-it-stops-functioning

器件型号:TMS320F28388D

您好!

这是一个程序、我从 eQEP_ex1_freq_cal 合并。

当它们被分离时、一切都能正常工作、但当我将这两个文件合并在一起时、

其他中断功能正常、但 eQEP 中断似乎只运行一次。

有人能告诉我什么问题吗?

第一个文件是我的程序。

第二个文件是 eqe2e.ti.com/.../5516.cm_5F00_common_5F00_config_5F00_c28x.ce2e.ti.com/.../eqep_5F00_ex1_5F00_freq_5F00_cal.cep_ex1_freq_cal.c

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

    eQEP 位于515线路上、中断位于594线路上、中断功能位于695线路上。

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

    您好:Hao Yu、

    eQEP ex 1使用 ePWM 模块生成用于频率计算的中断、因此您看不到 eQEP 中断。  最好使用 ex4 (频率)或 ex5 (速度和方向)作为参考、因为这两个示例使用 eQEP 模块内的单元计时器来生成周期性 eQEP 中断。 如果您需要进一步的澄清或帮助、请告诉我

    此致、

    Peter

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

    尊敬的 Peter:

    我认为您的答案解决了我的问题、但我还有几个问题。 因为我一直尝试以1的分辨率测量低频脉冲。 首先、我尝试使用 ex4 (中断频率)进行测量、但我发现将分辨率更改为1需要长时钟单元计时器(200000000U)。 因此、每次输入频率发生变化时、我都需要2秒钟才能到达正确的频率、但它是准确的。 ex1可以快速达到正确的频率、但它似乎有一个用于测量低频脉冲的死区、它在大约95Hz 时停止准确、是否有办法解决这个问题?  

    感谢回答我的问题!!!

    此致、

    Hao Yu  

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

    我还尝试使用 ePWM 中断、但它仍然只运行一次、我不确定是什么问题。 我已经将它与 ex1代码进行了比较、它是相同的。

    //#############################################################################
    //
    // FILE:   cm_common_config_c28x.c
    //
    // TITLE:  C28x Common Configurations to be used for the CM Side.
    //
    //! \addtogroup driver_example_list
    //! <h1>C28x Common Configurations</h1>
    //!
    //! This example configures the GPIOs and Allocates the shared peripherals
    //! according to the defines selected by the users.
    //!
    //
    //#############################################################################
    //
    //
    // $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 "pi.h"
    #include "pid.h"
    #include "math.h"
    #include "IQmathLib.h"
    
    //
    // Defines
    //
    #define TB_CLK    DEVICE_SYSCLK_FREQ / 2        // ePWM Time base clock is SYSCLK/2
    #define PWM_CLK   5000                      // PWM frequency as 5 kHz
    #define PRD_VAL   (TB_CLK / (PWM_CLK * 2))  // Calculate value period value
    #define UNIT_PERIOD  10000U // Specify the unit timeout period in
    #define myEPWM1_BASE    EPWM1_BASE
    #define myEQEP0_BASE    EQEP1_BASE
    #define base1    EPWM1_BASE
    #define base2   EPWM2_BASE
    #define EPWM_TIMER_TBPRD    625U
    #define EQEP1   EQEP1_BASE                                  //0x00005100U
    #define EQEP2   EQEP2_BASE                                  //0x00005140U
    #define INT_myEQEP0 INT_EQEP1
    #define INT_myEQEP0_INTERRUPT_ACK_GROUP INTERRUPT_ACK_GROUP5
    //Added 07/12
    #ifdef __TMS320C28XX_CLA__
    #pragma CODE_SECTION(PI_init,"Cla1Prog2");
    #endif
    #define IPC_CMD_READ_MEM   0x1001
    #define IPC_CMD_RESP       0x2001
    #define TEST_PASS          0x5555
    #define TEST_FAIL          0xAAAA
    // Added 0805 for using epwm interrupt to trigger
    // Base/max frequency is 10 kHz
    #define BASE_FREQ       10000
    // See Equation 5 in eqep_ex1_calculation.c
    #define FREQ_SCALER_PR  (((DEVICE_SYSCLK_FREQ / 128) * 8) / (2 * BASE_FREQ))
    typedef struct
    {
        uint32_t freqScalerPR;  // Parameter: Scaler converting 1/N cycles to a
                                // GLOBAL_Q freq (Q0) - independently with global Q
        uint32_t baseFreq;      // Parameter: Maximum freq
    
        _iq freqPR;             // Output: Freq in per-unit using capture unit
        int32_t freqHzPR;       // Output: Freq in Hz, measured using Capture unit
    
    } FreqCal_Object;
    
    typedef FreqCal_Object *FreqCal_Handle;
    #pragma DATA_SECTION(sendDataC28, "MSGRAM_CPU_TO_CM")
    
    //
    // Functions
    //
    void Board_init(void);                                      // setup for the board
    void EPWM_init(uint32_t base);                              // setup for epwm
    void EPWM_init_interrupt(uint32_t base);
    __interrupt void IPC_ISR1(void);
    __interrupt void cpuTimer0ISR(void);                        // setup for cpu0 interrupt
    __interrupt void cpuTimer1ISR(void);                        // setup for cpu1 interrupt
    __interrupt void cpuTimer2ISR(void);                        // setup for cpu2 interrupt
    __interrupt void epwmISR3(void);                            // setup for epwm3 interrupt
    // __interrupt void epwmISR4(void);
    void initCPUTimers(void);                                   // setup for cpu interrupt
    void configCPUTimer(uint32_t cpuTimer, uint32_t period);    // setup for cpu interrupt
    void setCPU(void);                                          // setup for cpu interrupt
    void EQEP_init(uint32_t base);                              // setup for eqep
    void setGPIO(void);                                         // setup for GPIOs
    void INTERRUPT_init(void);                                  // init interrupt
    void FreqCal_calculate(FreqCal_Handle, uint32_t);
    //__interrupt void IPC_ISR1(void);
    
    //
    //Global Variables
    //
    uint32_t oldcount = 0;          //eqep1, stores the previous position of the clock
    int32_t freq_Right = 0;         //eqep1, measured freq
    uint32_t count = 0;             //eqep1, check if eqep1 is operating
    uint32_t oldcount2 = 0;         //eqep2, stores the previous position of the clock
    int32_t freq_Left =0;           //eqep2, measured freq
    uint32_t count2 = 0;            //eqep2, check if eqep2 is operating
    uint32_t IPCCount1 = 0;
    uint32_t cpuTimer0IntCount = 0; //cpuTimer0, check if cpuTimer0 is operating
    uint32_t cpuTimer1IntCount = 0; //cpuTimer1, check if cpuTimer1 is operating
    uint32_t cpuTimer2IntCount = 0; //cpuTimer2, check if cpuTimer2 is operating
    uint32_t epwmCount = 0;
    uint32_t epwm2Count = 0;
    int targetRPM_Left = 0;         //cpuTimer1, get the input RPM of the left wheel
    int targetRPM_Right = 0;        //cpuTimer1, get the input RPM of the right wheel
    uint16_t dutycycle_Left = 0;    //epwm, turn the input RPM into the dutycycle of pwm
    uint16_t dutycycle_Right = 0;   //epwm, turn the input RPM into the dutycycle of pwm
    const float32_t freq1 = 5000.0; //??
    float32_t tmpLeft = 0;          //??
    float32_t tmpRight = 0;         //??
    float32_t kp=0.75;
    float32_t ki=0.06;
    float32_t kd=0.45;
    PID_Obj handle_Left = {0, 0, 0, 0, 0, 0, 0, -20, 80};
    PID_Obj handle_Right = {0, 0, 0, 0, 0, 0, 0, -20, 80};
    int temp = 0;
    FreqCal_Object freqLeft =
    {
        FREQ_SCALER_PR,  // freqScalerPR
        BASE_FREQ,       // baseFreq
        0, 0,   // Initialize outputs to zero
    };
    FreqCal_Object freqRight =
    {
        FREQ_SCALER_PR,  // freqScalerPR
        BASE_FREQ,       // baseFreq
        0, 0,   // Initialize outputs to zero
    };
    
    //Added 07/12
    float sendDataC28[10];
    uint32_t pass;
    float receiveDataC28[9];
    
    //vehicle Added 07/12
    const float rw = 0.08; //radius of wheel
    const float R = 0.17; //half distance of two wheel
    float controlmatrix[2][2];
    float inv_controlmatrix[2][2];
    
    //parameters Added 07/12
    float feedBackGainEpsilon = 1;
    float feedBackGainB = 0.01;
    
    float sideBysideOmegaGain = 15;
    
    float v_max = 0.25;
    float w_max = 0.5;
    int tmp1 = 0;
    
    
    typedef struct point
    {
        float set_x[4];
        float set_y[4];
        float set_t[4];
        int point_number;
    
    }via_point;
    int path_type = 0;
    const float RS_EPS = 1e-4;
    
    void main(void)
    {
        //
        // Initialize device clock and peripherals
        //
        Device_init();
    
        //
        // Boot CM core
        //
    #ifdef _FLASH
        Device_bootCM(BOOTMODE_BOOT_TO_FLASH_SECTOR0);
    #else
        Device_bootCM(BOOTMODE_BOOT_TO_S0RAM);
    #endif
    
        //
        // Disable pin locks and enable internal pull-ups.
        //
        Device_initGPIO();
    
    #ifdef ETHERNET
        //
        // Set up EnetCLK to use SYSPLL as the clock source and set the
        // clock divider to 2.
        //
        // This way we ensure that the PTP clock is 100 MHz. Note that this value
        // is not automatically/dynamically known to the CM core and hence it needs
        // to be made available to the CM side code beforehand.
        SysCtl_setEnetClk(SYSCTL_ENETCLKOUT_DIV_2, SYSCTL_SOURCE_SYSPLL);
    
        //
        // Configure the GPIOs for ETHERNET.
        //
    
        //
        // MDIO Signals
        //
        GPIO_setPinConfig(GPIO_105_ENET_MDIO_CLK);
        GPIO_setPinConfig(GPIO_106_ENET_MDIO_DATA);
    
        //
        // Use this only for RMII Mode
        //GPIO_setPinConfig(GPIO_73_ENET_RMII_CLK);
        //
    
        //
        //MII Signals
        //
        GPIO_setPinConfig(GPIO_109_ENET_MII_CRS);
        GPIO_setPinConfig(GPIO_110_ENET_MII_COL);
    
        GPIO_setPinConfig(GPIO_75_ENET_MII_TX_DATA0);
        GPIO_setPinConfig(GPIO_122_ENET_MII_TX_DATA1);
        GPIO_setPinConfig(GPIO_123_ENET_MII_TX_DATA2);
        GPIO_setPinConfig(GPIO_124_ENET_MII_TX_DATA3);
    
        //
        //Use this only if the TX Error pin has to be connected
        //GPIO_setPinConfig(GPIO_46_ENET_MII_TX_ERR);
        //
    
        GPIO_setPinConfig(GPIO_118_ENET_MII_TX_EN);
    
        GPIO_setPinConfig(GPIO_114_ENET_MII_RX_DATA0);
        GPIO_setPinConfig(GPIO_115_ENET_MII_RX_DATA1);
        GPIO_setPinConfig(GPIO_116_ENET_MII_RX_DATA2);
        GPIO_setPinConfig(GPIO_117_ENET_MII_RX_DATA3);
        GPIO_setPinConfig(GPIO_113_ENET_MII_RX_ERR);
        GPIO_setPinConfig(GPIO_112_ENET_MII_RX_DV);
    
        GPIO_setPinConfig(GPIO_44_ENET_MII_TX_CLK);
        GPIO_setPinConfig(GPIO_111_ENET_MII_RX_CLK);
    
        //
        //Power down pin to bring the external PHY out of Power down
        //
        GPIO_setDirectionMode(108, GPIO_DIR_MODE_OUT);
        GPIO_setPadConfig(108, GPIO_PIN_TYPE_PULLUP);
        GPIO_writePin(108,1);
    
        //
        //PHY Reset Pin to be driven High to bring external PHY out of Reset
        //
    
        GPIO_setDirectionMode(119, GPIO_DIR_MODE_OUT);
        GPIO_setPadConfig(119, GPIO_PIN_TYPE_PULLUP);
        GPIO_writePin(119,1);
    #endif
    
    #ifdef MCAN
        //
        // Setting the MCAN Clock.
        //
        SysCtl_setMCANClk(SYSCTL_MCANCLK_DIV_4);
    
        //
        // Configuring the GPIOs for MCAN.
        //
        GPIO_setPinConfig(DEVICE_GPIO_CFG_MCANRXA);
        GPIO_setPinConfig(DEVICE_GPIO_CFG_MCANTXA);
    #endif
    
    #ifdef CANA
        //
        // Configuring the GPIOs for CAN A.
        //
        GPIO_setPinConfig(DEVICE_GPIO_CFG_CANRXA);
        GPIO_setPinConfig(DEVICE_GPIO_CFG_CANTXA);
    
        //
        // Allocate Shared Peripheral CAN A to the CM Side.
        //
        SysCtl_allocateSharedPeripheral(SYSCTL_PALLOCATE_CAN_A,0x1U);
    #endif
    
    #ifdef CANB
        //
        // Configuring the GPIOs for CAN B.
        //
        GPIO_setPinConfig(DEVICE_GPIO_CFG_CANRXB);
        GPIO_setPinConfig(DEVICE_GPIO_CFG_CANTXB);
    
        //
        // Allocate Shared Peripheral CAN B to the CM Side.
        //
        SysCtl_allocateSharedPeripheral(SYSCTL_PALLOCATE_CAN_B,0x1U);
    #endif
    
    #ifdef UART
        //
        // Configure GPIO85 as the UART Rx pin.
        //
        GPIO_setPinConfig(GPIO_85_UARTA_RX);
        GPIO_setDirectionMode(85, GPIO_DIR_MODE_IN);
        GPIO_setPadConfig(85, GPIO_PIN_TYPE_STD);
        GPIO_setQualificationMode(85, GPIO_QUAL_ASYNC);
    
        //
        // Configure GPIO84 as the UART Tx pin.
        //
        GPIO_setPinConfig(GPIO_84_UARTA_TX);
        GPIO_setDirectionMode(84, GPIO_DIR_MODE_OUT);
        GPIO_setPadConfig(84, GPIO_PIN_TYPE_STD);
        GPIO_setQualificationMode(84, GPIO_QUAL_ASYNC);
    #endif
    
    #ifdef USB
    #ifdef USE_20MHZ_XTAL
        //
        // Set up the auxiliary PLL so a 60 MHz output clock is provided to the USB module.
        // This fixed frequency is required for all USB operations.
        //
        SysCtl_setAuxClock(SYSCTL_AUXPLL_OSCSRC_XTAL |
                           SYSCTL_AUXPLL_IMULT(48) |
                           SYSCTL_REFDIV(2U) | SYSCTL_ODIV(4U) |
                           SYSCTL_AUXPLL_DIV_2 |
                           SYSCTL_AUXPLL_ENABLE |
                           SYSCTL_DCC_BASE_0);
    #else
        //
        // Set up the auxiliary PLL so a 60 MHz output clock is provided to the USB module.
        // This fixed frequency is required for all USB operations.
        //
        SysCtl_setAuxClock(SYSCTL_AUXPLL_OSCSRC_XTAL |
                           SYSCTL_AUXPLL_IMULT(48) |
                           SYSCTL_REFDIV(2U) | SYSCTL_ODIV(5U) |
                           SYSCTL_AUXPLL_DIV_2 |
                           SYSCTL_AUXPLL_ENABLE |
                           SYSCTL_DCC_BASE_0);
    #endif
    
        //
        // Allocate Shared Peripheral USB to the CM Side.
        //
        SysCtl_allocateSharedPeripheral(SYSCTL_PALLOCATE_USBA, 1);
    
        GPIO_setPinConfig(GPIO_0_GPIO0);
        GPIO_setPadConfig(0, GPIO_PIN_TYPE_STD);
        GPIO_setDirectionMode(0, GPIO_DIR_MODE_OUT);
        GPIO_setMasterCore(0, GPIO_CORE_CM);
    
        //
        // Set the master core of GPIOs to CM.
        //
        GPIO_setMasterCore(42, GPIO_CORE_CM);
        GPIO_setMasterCore(43, GPIO_CORE_CM);
        GPIO_setMasterCore(46, GPIO_CORE_CM);
        GPIO_setMasterCore(47, GPIO_CORE_CM);
        GPIO_setMasterCore(120, GPIO_CORE_CM);
        GPIO_setMasterCore(121, GPIO_CORE_CM);
    
        //
        // Set the USB DM and DP GPIOs.
        //
        GPIO_setAnalogMode(42, GPIO_ANALOG_ENABLED);
        GPIO_setAnalogMode(43, GPIO_ANALOG_ENABLED);
    
        //
        // Set the direction for VBUS and ID.
        //
        GPIO_setDirectionMode(46, GPIO_DIR_MODE_IN);
        GPIO_setDirectionMode(47, GPIO_DIR_MODE_IN);
    
        //
        // Configure the Power Fault.
        //
        GPIO_setMasterCore(120, GPIO_CORE_CM);
        GPIO_setDirectionMode(120, GPIO_DIR_MODE_IN);
    
        //
        // Configure the External Power Signal Enable.
        //
        GPIO_setMasterCore(121, GPIO_CORE_CM);
        GPIO_setDirectionMode(121, GPIO_DIR_MODE_OUT);
        GPIO_writePin(121, 1);
    
        //
        // Set the CM Clock to run at 120MHz.
        // The CM Clock is a fractional multiple of the AUXPLL Clock (120 Mhz) from
        // which the USB Clock (60 MHz) is derived.
        //
        SysCtl_setCMClk(SYSCTL_CMCLKOUT_DIV_1, SYSCTL_SOURCE_AUXPLL);
    #endif
    
        //Modified
        Interrupt_initModule();
        Interrupt_initVectorTable();
    
        IPC_clearFlagLtoR(IPC_CPU1_L_CM_R, IPC_FLAG_ALL);
        IPC_registerInterrupt(IPC_CPU1_L_CM_R, IPC_INT1, IPC_ISR1);
        // IPC_sync(IPC_CPU1_L_CM_R, IPC_FLAG31);
    
        Board_init();
    
        EINT;
        ERTM;
    
        while(1) {;}
    }
    
    void Board_init(void) {
        EALLOW;
    
        setGPIO();
        EPWM_init(base1);
        EPWM_init(base2);
        EQEP_init(EQEP1_BASE);
        EQEP_init(EQEP2_BASE);
        EPWM_init_interrupt(EPWM3_BASE);
        INTERRUPT_init();
        setCPU();
    
        EDIS;
    }
    
    void setGPIO(void) {
        //EQEP1
        GPIO_setPinConfig(GPIO_20_EQEP1_A);
        GPIO_setPadConfig(20, GPIO_PIN_TYPE_STD);
        GPIO_setPinConfig(GPIO_11_EQEP1_B);
        GPIO_setPadConfig(11, GPIO_PIN_TYPE_STD);
    
        //EQEP2
        GPIO_setPinConfig(GPIO_54_EQEP2_A);
        GPIO_setPadConfig(54, GPIO_PIN_TYPE_STD);
        GPIO_setPinConfig(GPIO_55_EQEP2_B);
        GPIO_setPadConfig(55, GPIO_PIN_TYPE_STD);
    
        //EPWM1
        GPIO_setPinConfig(GPIO_0_EPWM1A);
        GPIO_setPadConfig(0, GPIO_PIN_TYPE_STD);
    
        //EPWM2
        GPIO_setPinConfig(GPIO_2_EPWM2A);
        GPIO_setPadConfig(2, GPIO_PIN_TYPE_STD);
    
        //set GPIO1 for reverse switch left
        GPIO_setPinConfig(GPIO_1_GPIO1);
        GPIO_setPadConfig(1, GPIO_PIN_TYPE_STD);
        GPIO_setDirectionMode(1, GPIO_DIR_MODE_OUT);
    
        //set GPIO3 for reverse switch right
        GPIO_setPinConfig(GPIO_3_GPIO3);
        GPIO_setPadConfig(3, GPIO_PIN_TYPE_STD);
        GPIO_setDirectionMode(3, GPIO_DIR_MODE_OUT);
    
        //set GPIO8 for forward switch left
        GPIO_setPinConfig(GPIO_8_GPIO8);
        GPIO_setPadConfig(8, GPIO_PIN_TYPE_STD);
        GPIO_setDirectionMode(8, GPIO_DIR_MODE_OUT);
    
        //set GPIO9 for forward switch right
        GPIO_setPinConfig(GPIO_9_GPIO9);
        GPIO_setPadConfig(9, GPIO_PIN_TYPE_STD);
        GPIO_setDirectionMode(9, GPIO_DIR_MODE_OUT);
    }
    
    void EPWM_init_interrupt(uint32_t base) {
        //
        // 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(base, 0);
        EPWM_setTimeBaseCounter(base, 0);
    
        //
        // Disable the shadow load; the load will be immediate instead
        //
        EPWM_disableCounterCompareShadowLoadMode(base,
                                                 EPWM_COUNTER_COMPARE_A);
        EPWM_disableCounterCompareShadowLoadMode(base,
                                                 EPWM_COUNTER_COMPARE_B);
    
        //
        // Set the compare A value to half the period value, compare B to 0
        //
        EPWM_setCounterCompareValue(base, EPWM_COUNTER_COMPARE_A, PRD_VAL/2);
        //
        // Set action qualifier behavior on compare A events
        // - EPWM1A --> 1 when CTR = CMPA and increasing
        // - EPWM1A --> 0 when CTR = CMPA and decreasing
        //
        EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_HIGH,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
        EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_LOW,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    
        //
        // Configure EPWM1B to be complementary to EPWM1A
        //
        EPWM_setDeadBandDelayPolarity(base, EPWM_DB_FED,
                                      EPWM_DB_POLARITY_ACTIVE_LOW);
        EPWM_setDeadBandDelayMode(base, EPWM_DB_FED, true);
        EPWM_setDeadBandDelayMode(base, EPWM_DB_RED, true);
    
        //
        // Enable interrupt when the counter is equal to 0
        //
        EPWM_setInterruptSource(base, EPWM_INT_TBCTR_ZERO);
        EPWM_enableInterrupt(base);
    
        //
        // Interrupt on first event
        //
        EPWM_setInterruptEventCount(base, 1);
    
        //
        // Set the time base clock prescaler to /1
        //
        EPWM_setClockPrescaler(base, EPWM_CLOCK_DIVIDER_1,
                               EPWM_HSCLOCK_DIVIDER_1);
    
        //
        // Set the period value; don't shadow the register
        //
        EPWM_setPeriodLoadMode(base, EPWM_PERIOD_DIRECT_LOAD);
        EPWM_setTimeBasePeriod(base, PRD_VAL);
    
        //
        // Put the time base counter into up-down count mode
        //
        EPWM_setTimeBaseCounterMode(base, EPWM_COUNTER_MODE_UP_DOWN);
    
        //
        // Sync the ePWM time base clock
        //
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    }
    
    void EPWM_init(uint32_t base) {
        // setup TBCLK for EPWM
        EPWM_setTimeBasePeriod(base, EPWM_TIMER_TBPRD);
        EPWM_setPhaseShift(base, 0U);
        EPWM_setTimeBaseCounter(base, 0U);
        EPWM_setTimeBaseCounterMode(base, EPWM_COUNTER_MODE_UP_DOWN);
        EPWM_disablePhaseShiftLoad(base);
    
        // setup epwm prescalar
        EPWM_setClockPrescaler(base, EPWM_CLOCK_DIVIDER_4, EPWM_HSCLOCK_DIVIDER_4);
    
        // setup compare
        EPWM_setCounterCompareValue(base, EPWM_COUNTER_COMPARE_A, 1*EPWM_TIMER_TBPRD/100);
    
        // setup actions
        EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
        EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
        EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
        EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    }
    
    void EQEP_init(uint32_t base) {
        //myEQEP0 initialization
    
        EQEP_SourceSelect source_myEQEP0 =
        {
            EQEP_SOURCE_DEVICE_PIN,         // eQEPA source
            EQEP_SOURCE_DEVICE_PIN,     // eQEPB source
            EQEP_SOURCE_DEVICE_PIN,     // eQEP Index source
        };
        // Selects the source for eQEPA/B/I signals
        EQEP_selectSource(base, source_myEQEP0);
        // Set the strobe input source of the eQEP module.
        EQEP_setStrobeSource(base,EQEP_STROBE_FROM_GPIO);
        // Sets the polarity of the eQEP module's input signals.
        EQEP_setInputPolarity(base,false,false,false,false);
        // Configures eQEP module's quadrature decoder unit.
        EQEP_setDecoderConfig(base, (EQEP_CONFIG_UP_COUNT | EQEP_CONFIG_2X_RESOLUTION | EQEP_CONFIG_NO_SWAP | EQEP_CONFIG_IGATE_DISABLE));
        // Set the emulation mode of the eQEP module.
        EQEP_setEmulationMode(base,EQEP_EMULATIONMODE_RUNFREE);
        // Configures eQEP module position counter unit.
        EQEP_setPositionCounterConfig(base,EQEP_POSITION_RESET_1ST_IDX,4294967295U);
        // Sets the current encoder position.
        EQEP_setPosition(base,0U);
        // Enables the eQEP module unit timer.
        EQEP_enableUnitTimer(base,2000000U);
        // Disables the eQEP module watchdog timer.
        EQEP_disableWatchdog(base);
        // Configures the quadrature modes in which the position count can be latched.
        EQEP_setLatchMode(base,(EQEP_LATCH_UNIT_TIME_OUT|EQEP_LATCH_RISING_STROBE|EQEP_LATCH_RISING_INDEX));
        // Set the quadrature mode adapter (QMA) module mode.
        EQEP_setQMAModuleMode(base,EQEP_QMA_MODE_BYPASS);
        // Disable Direction Change During Index
        EQEP_disableDirectionChangeDuringIndex(base);
        // Configures the mode in which the position counter is initialized.
        EQEP_setPositionInitMode(base,(EQEP_INIT_DO_NOTHING));
        // Sets the software initialization of the encoder position counter.
        EQEP_setSWPositionInit(base,true);
        // Sets the init value for the encoder position counter.
        EQEP_setInitialPosition(base,0U);
        // Enables the eQEP module.
        EQEP_enableModule(base);
        // Configures eQEP module edge-capture unit.
        EQEP_setCaptureConfig(base,EQEP_CAPTURE_CLK_DIV_128,EQEP_UNIT_POS_EVNT_DIV_8);
        // Enables the eQEP module edge-capture unit.
        EQEP_enableCapture(base);
    }
    
    void INTERRUPT_init() {
        //Interrupt Setting for epwmISR3
        Interrupt_register(INT_EPWM3, &epwmISR3);
        Interrupt_enable(INT_EPWM3);
    
        /*
        Interrupt_register(INT_EPWM4, &epwmISR4);
        Interrupt_enable(INT_EPWM4);
        */
    
        //Interrupt Setting for cpuTimer0ISR
        Interrupt_register(INT_TIMER0, &cpuTimer0ISR);
        Interrupt_enable(INT_TIMER0);
    
        //Interrupt Setting for cpuTimer1ISR
        Interrupt_register(INT_TIMER1, &cpuTimer1ISR);
        Interrupt_enable(INT_TIMER1);
    
        //Interrupt Setting for cpuTimer2ISR
        Interrupt_register(INT_TIMER2, &cpuTimer2ISR);
        Interrupt_enable(INT_TIMER2);
    }
    
    void setCPU() {
        initCPUTimers();
    
        cpuTimer0IntCount = 0;
        cpuTimer1IntCount = 0;
        cpuTimer2IntCount = 0;
    
        configCPUTimer(CPUTIMER0_BASE, 10000);
        configCPUTimer(CPUTIMER1_BASE, 10000);
        configCPUTimer(CPUTIMER2_BASE, 10000);
    
        CPUTimer_enableInterrupt(CPUTIMER0_BASE);
        CPUTimer_enableInterrupt(CPUTIMER1_BASE);
        CPUTimer_enableInterrupt(CPUTIMER2_BASE);
    
        CPUTimer_startTimer(CPUTIMER0_BASE);
        CPUTimer_startTimer(CPUTIMER1_BASE);
        CPUTimer_startTimer(CPUTIMER2_BASE);
    }
    
    void initCPUTimers(void) {
        CPUTimer_setPeriod(CPUTIMER0_BASE, 0xFFFFFFFF);
        CPUTimer_setPeriod(CPUTIMER1_BASE, 0xFFFFFFFF);
        CPUTimer_setPeriod(CPUTIMER2_BASE, 0xFFFFFFFF);
    
        CPUTimer_setPreScaler(CPUTIMER0_BASE, 0);
        CPUTimer_setPreScaler(CPUTIMER1_BASE, 0);
        CPUTimer_setPreScaler(CPUTIMER2_BASE, 0);
    
        CPUTimer_stopTimer(CPUTIMER0_BASE);
        CPUTimer_stopTimer(CPUTIMER1_BASE);
        CPUTimer_stopTimer(CPUTIMER2_BASE);
    
        CPUTimer_reloadTimerCounter(CPUTIMER0_BASE);
        CPUTimer_reloadTimerCounter(CPUTIMER1_BASE);
        CPUTimer_reloadTimerCounter(CPUTIMER2_BASE);
    
        cpuTimer0IntCount = 0;
        cpuTimer1IntCount = 0;
        cpuTimer2IntCount = 0;
    }
    
    void configCPUTimer(uint32_t cpuTimer, uint32_t period) {
        uint32_t temp, freq = DEVICE_SYSCLK_FREQ;
    
        //
        // Initialize timer period:
        //
        temp = ((freq / 1000000) * period);
        CPUTimer_setPeriod(cpuTimer, temp);
    
        //
        // Set pre-scale counter to divide by 1 (SYSCLKOUT):
        //
        CPUTimer_setPreScaler(cpuTimer, 0);
    
        //
        // Initializes timer control register. The timer is stopped, reloaded,
        // free run disabled, and interrupt enabled.
        // Additionally, the free and soft bits are set
        //
        CPUTimer_stopTimer(cpuTimer);
        CPUTimer_reloadTimerCounter(cpuTimer);
        CPUTimer_setEmulationMode(cpuTimer,
                                  CPUTIMER_EMULATIONMODE_STOPAFTERNEXTDECREMENT);
        CPUTimer_enableInterrupt(cpuTimer);
    
        //
        // Resets interrupt counters for the three cpuTimers
        //
        if (cpuTimer == CPUTIMER0_BASE) {
            cpuTimer0IntCount = 0;
        }
        if (cpuTimer == CPUTIMER1_BASE) {
            cpuTimer1IntCount = 0;
        }
        if (cpuTimer == CPUTIMER2_BASE) {
            cpuTimer2IntCount = 0;
        }
    }
    
    __interrupt void epwmISR3(void) {
        epwmCount++;
        FreqCal_calculate(&freqLeft, EQEP1_BASE);
    
        EPWM_clearEventTriggerInterruptFlag(EPWM3_BASE);
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP2);
    }
    
    /*
    __interrupt void epwmISR4(void) {
        epwm2Count++;
        FreqCal_calculate(&freqRight, EQEP2_BASE);
    
        EPWM_clearEventTriggerInterruptFlag(EPWM4_BASE);
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP2);
    }
    */
    
    __interrupt void cpuTimer0ISR(void) {
        /*
        //send what
        sendDataC28[0] = 0;
        sendDataC28[1] = 0;
        sendDataC28[2] = 0;
        sendDataC28[3] = 0;
        IPC_sendCommand(IPC_CPU1_L_CM_R, IPC_FLAG0, IPC_ADDR_CORRECTION_ENABLE,
                        IPC_CMD_READ_MEM, (uint32_t)sendDataC28, 10);
    
        IPC_waitForAck(IPC_CPU1_L_CM_R, IPC_FLAG0);
        if(IPC_getResponse(IPC_CPU1_L_CM_R) == TEST_PASS){
            pass = 1;
        }
        else{
            pass = 0;
        }
        */
    
        cpuTimer0IntCount++;
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
    }
    
    __interrupt void cpuTimer1ISR(void) {
        PID_setGains(&handle_Left, kp, ki, kd);
        PID_setGains(&handle_Right, kp, ki, kd);
        //step.1-1 turn rpm into dutycycle
        //available zone [Forward:10~80 RPM, Backward:6~20 RPM]
        if (targetRPM_Left<0){
            //PID_run_parallel [handle, DesireValue, FeedbackValue, FeedforwardValue, Pointer to the output]
            PID_run_parallel(&handle_Left, targetRPM_Left, -freq_Left/4, 0, &tmpLeft);
            dutycycle_Left = (1-(-tmpLeft*0.0165+0.1928))*100;
        }
        else{
            PID_run_parallel(&handle_Left, targetRPM_Left, freq_Left/4, 0, &tmpLeft);
            dutycycle_Left = (1-(tmpLeft*0.0041+0.2963))*100;
        }
        if (targetRPM_Right<0){
            PID_run_parallel(&handle_Right, targetRPM_Right, -freq_Right/4, 0, &tmpRight);
            dutycycle_Right = (1-(-tmpRight*0.0171+0.1928))*100;
        }
        else{
            PID_run_parallel(&handle_Right, targetRPM_Right, freq_Right/4, 0, &tmpRight);
            dutycycle_Right = (1-(tmpRight*0.0041+0.2996))*100;
        }
    
        if (dutycycle_Left>=70){
            EPWM_setCounterCompareValue(base1, EPWM_COUNTER_COMPARE_A, 99*EPWM_TIMER_TBPRD/100);
            PID_setUi(&handle_Left, 0);
        }
        else{
            EPWM_setCounterCompareValue(base1, EPWM_COUNTER_COMPARE_A, dutycycle_Left*EPWM_TIMER_TBPRD/100);
        }
        if (dutycycle_Right>=70){
            EPWM_setCounterCompareValue(base2, EPWM_COUNTER_COMPARE_A, 99*EPWM_TIMER_TBPRD/100);
            PID_setUi(&handle_Right, 0);
        }
        else{
            EPWM_setCounterCompareValue(base2, EPWM_COUNTER_COMPARE_A, dutycycle_Right*EPWM_TIMER_TBPRD/100);
        }
        //step.1-2 decide the direction
        //the direction for the left wheel
        if (targetRPM_Left>0){
            GPIO_writePin(8,1);
            GPIO_writePin(1,0);
        }
        else if (targetRPM_Left<0){
            GPIO_writePin(8,0);
            GPIO_writePin(1,1);
        }
        else{
            GPIO_writePin(8,0);
            GPIO_writePin(1,0);
        }
        //the direction for the right wheel
        if (targetRPM_Right>0){
            GPIO_writePin(9,1);
            GPIO_writePin(3,0);
        }
        else if (targetRPM_Right<0){
            GPIO_writePin(9,0);
            GPIO_writePin(3,1);
        }
        else{
            GPIO_writePin(9,0);
            GPIO_writePin(3,0);
        }
    
        //step.2 let f2838x generate the dutycycle we want
    
        cpuTimer1IntCount++;
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
    }
    
    __interrupt void cpuTimer2ISR(void) {
        cpuTimer2IntCount++;
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
    }
    
    __interrupt void IPC_ISR1() {
        uint32_t command, addr, data;
        int i;
        bool status = false;
        IPC_readCommand(IPC_CPU1_L_CM_R, IPC_FLAG1, IPC_ADDR_CORRECTION_ENABLE,
                        &command, &addr, &data);
        if(command == IPC_CMD_READ_MEM)
        {
            status = true;
            for(i=0; i<data; i++)
            {
                receiveDataC28[i] = *((float *)addr + i);
            }
        }
        if(status)
        {
            IPC_sendResponse(IPC_CPU1_L_CM_R, TEST_PASS);
        }
        else
        {
            IPC_sendResponse(IPC_CPU1_L_CM_R, TEST_FAIL);
        }
        IPC_ackFlagRtoL(IPC_CPU1_L_CM_R, IPC_FLAG1);
        //Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP11);
        IPCCount1++;
    }
    
    void FreqCal_calculate(FreqCal_Object *p, uint32_t base) {
        uint32_t temp;
        //
        // **** Frequency calculation using eQEP capture counter ****
        //
        // Check for unit position event
        //
        if((EQEP_getStatus(base) & EQEP_STS_UNIT_POS_EVNT) != 0)
        {
            //
            // No capture overflow
            //
            if((EQEP_getStatus(base) & EQEP_STS_CAP_OVRFLW_ERROR) == 0)
            {
                temp = (uint32_t)EQEP_getCapturePeriodLatch(base);
            }
            else
            {
                //
                // Capture overflow, saturate the result
                //
                temp = 0xFFFF;
            }
    
            //
            // p->freqPR = X / [(t2 - t1) * 10kHz]
            //
            p->freqPR = _IQdiv(p->freqScalerPR, temp);
            temp = p->freqPR;
    
            if(temp > _IQ(1))
            {
                p->freqPR = _IQ(1);
            }
            else
            {
                p->freqPR = temp;
            }
    
            //
            // Q0 = Q0 * GLOBAL_Q => _IQXmpy(), X = GLOBAL_Q
            // p->freqHzPR = (p->freqPR) * 10kHz = X / (t2 - t1)
            //
            p->freqHzPR = _IQmpy(p->baseFreq, p->freqPR);
    
            //
            // Clear unit position event flag and overflow error flag
            //
            EQEP_clearStatus(base, (EQEP_STS_UNIT_POS_EVNT |
                                          EQEP_STS_CAP_OVRFLW_ERROR));
        }
    }
    

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

    您好:Hao Yu、

    当您将 ex4与 eQEP 中断一起使用时、您的中断是否正常工作? 调试代码会很困难、因为配置看起来是相同的、但我需要更详细地了解。 您能否尝试单步执行您的代码来查看为什么中断只发生一次?  

    关于仅高频脉冲精确度的注意事项、这是由于使用了估算频率的方法。 通常、在电机感应应用中、使用不同的技术、具体取决于它是测量高频输入还是低频输入、并且软件会根据传入信号动态变化。 eQEP 的边沿捕获单元专为测量低频输入而设计、您可以在 TRM 的 eQEP 章节中找到有关该部件的更多信息。 我认为电机控制 SDK 中有用于此动态开关的示例代码

    此致、

    Peter

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

    尊敬的 Peter:

    我这次尝试在程序中执行1。 因为使用了 EPWM1和 EPWM2、所以我尝试改用 EPWM3。

    Line496、I init epwm3用于中断。 我在595行初始化 eQEP。 然后、我在第644行初始化中断。 最后、中断功能位于第746行。

    我也会尝试从 TRM 的 eQEP 章节中找到一些内容、谢谢。

    此致、

    Hao Yu

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

    尊敬的 Peter:

    我发现了什么是错误!!! 我在第751行中输入了一个拼写错误、在 epwmISR 的中断中、我意外键入了"interrupt_ACK_group2"、它应该是"interrupt_ACK_Group3"。 在改变这个之后,它是有效的!!! 但我想问的是、每个 INTERRUPT_ACK_GROUPx 之间有何区别? 我要将问题标记为已解决。

    感谢您的帮助!!!

    此致、

    Hao Yu

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

    您好:Hao Yu、

    很高兴您能够解决此问题! 关于中断问题、这称为 PIE 通道映射、每个外设都有一个连接到 CPU 的多路复用信号、可用于发出中断。 如果您配置了不正确的中断、那么您将无法获得正确的连接、并且无法发出中断、从而导致您看到的行为。 您可以在 C2000 Academy 深度潜水模块中阅读有关中断的更多信息、该模块相当深入、同时提供易于阅读的说明。

    此致、

    Peter