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:TMS320F280049C

Guru**** 2524550 points
Other Parts Discussed in Thread: C2000WARE

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

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

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

大家好!

我正在使用代码 epwm_ex13_up_aq.c。我已在此处附加了代码。  

其目标是:

1) 1)将占空比更改至50%、并将其固定为50%。

2)提供由看门狗中的变量"Ph"定义的相移

为了实现这一点、我 在看门狗中有两个标志:AshikFlag 和 loop_counter。 若要启用相移、loop_counter 应等于 AshikFlag。

我目前面临着一些挑战:

1) 1)在较高的频率下、当我将 LOOP_COUNTER 更改为 AshikFlag 时、EPWM2变得不稳定。 我认为它是因为我在 EPWM2的 ISR 函数中放了一个硬代码。 有更智能的方法来实现它吗?

代码已添加。

谢谢。

Ashik

//###########################################################################
//
// FILE:   epwm_ex13_up_aq.c
//
// TITLE:  Action Qualifier Module - Using up count.
//
//! \addtogroup driver_example_list
//! <h1> EPWM Action Qualifier (epwm_up_aq)</h1>
//!
//! This example configures ePWM1, ePWM2, ePWM3 to produce an
//! waveform with independent modulation on EPWMxA and
//! EPWMxB.
//!
//! The compare values CMPA and CMPB are modified within the ePWM's ISR.
//!
//! The TB counter is in up count mode for this example.
//!
//! View the EPWM1A/B(GPIO0 & GPIO1), EPWM2A/B(GPIO2 & GPIO3)
//! and EPWM3A/B(GPIO4 & GPIO5) waveforms via an oscilloscope.
//!
//
//###########################################################################
//
//
// $Copyright:
// Copyright (C) 2021 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 "board.h"
//
// Defines
//
#define EPWM1_TIMER_TBPRD  100  // Period register //2000
#define EPWM1_MAX_CMPA     50   //1000
#define EPWM1_MIN_CMPA       0
#define EPWM1_MAX_CMPB     50     //1000
#define EPWM1_MIN_CMPB       0

#define EPWM2_TIMER_TBPRD  100  // Period register
#define EPWM2_MAX_CMPA     50  //1950
#define EPWM2_MIN_CMPA      0   //50
#define EPWM2_MAX_CMPB     50  //1950
#define EPWM2_MIN_CMPB      0   //50

#define EPWM3_TIMER_TBPRD  100  // Period register
#define EPWM3_MAX_CMPA      50
#define EPWM3_MIN_CMPA       0
#define EPWM3_MAX_CMPB      50
#define EPWM3_MIN_CMPB       0

#define EPWM_CMP_UP           1
#define EPWM_CMP_DOWN         0

//
// Globals
//
typedef struct
{
    uint32_t epwmModule;
    uint16_t epwmCompADirection;
    uint16_t epwmCompBDirection;
    uint16_t epwmTimerIntCount;
    uint16_t ePWMDone;
    uint16_t epwmMaxCompA;
    uint16_t epwmMinCompA;
    uint16_t epwmMaxCompB;
    uint16_t epwmMinCompB;
} epwmInfo;

epwmInfo epwm1Info;
epwmInfo epwm2Info;
epwmInfo epwm3Info;
uint16_t AshikFlag = 0 ; //Ashik Added
uint16_t Ph = 0 ; //Ashik Added
uint16_t loop_counter = 0 ; //Ashik Added

volatile uint16_t compAVal, compBVal;

//
//  Function Prototypes
//
void initEPWM1(void);
void initEPWM2(void);
void initEPWM3(void);
__interrupt void epwm1ISR(void);
__interrupt void epwm2ISR(void);
__interrupt void epwm3ISR(void);
void updateCompare(epwmInfo*);

//
// Main
//
void main(void)
{
    //
    // Initialize device clock and peripherals
    //
    Device_init();

    //
    // Disable pin locks and enable internal pull-ups.
    //
    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();

    //
    // For this case just init GPIO pins for ePWM1, ePWM2, ePWM3
    //
    Board_init();

    //
    // Interrupts that are used in this example are re-mapped to
    // ISR functions found within this file.
    //
    Interrupt_register(INT_EPWM1, &epwm1ISR);
    Interrupt_register(INT_EPWM2, &epwm2ISR);
    Interrupt_register(INT_EPWM3, &epwm3ISR);

    //
    // Disable sync(Freeze clock to PWM as well)
    //
    SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);

    // Initialize PWM1 without phase shift as master
    initEPWM1();

    // Initialize PWM2 with phase shift of X
    initEPWM2();
    //EPWM_selectPeriodLoadEvent(myEPWM2_BASE, EPWM_SHADOW_LOAD_MODE_SYNC);
    //EPWM_setPhaseShift(myEPWM2_BASE, Ph); //ashik added Ph
   // EPWM_setTimeBaseCounter(myEPWM2_BASE, Ph); //ashik added Ph

    initEPWM3();

    EPWM_setSyncOutPulseMode(EPWM1_BASE, EPWM_SYNC_OUT_PULSE_ON_COUNTER_ZERO);

    //
    // ePWM2 uses the ePWM 1 SYNCO as its SYNCIN.
    // ePWM2 SYNCO is generated from its SYNCIN, which is ePWM1 SYNCO
    //
    EPWM_setSyncOutPulseMode(myEPWM2_BASE, EPWM_SYNC_OUT_PULSE_ON_EPWMxSYNCIN);

    //
    // ePWM4 uses the ePWM 1 SYNCO as its SYNCIN.
    //
    //SysCtl_setSyncInputConfig(SYSCTL_SYNC_IN_EPWM4, SYSCTL_SYNC_IN_SRC_EPWM1SYNCOUT);
    //
    // Enable all phase shifts.
    //
    EPWM_enablePhaseShiftLoad(myEPWM2_BASE);

    //
    // Enable sync and clock to PWM
    //
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);

    //
    // Enable interrupts required for this example
    //
    Interrupt_enable(INT_EPWM1);
    Interrupt_enable(INT_EPWM2);
    Interrupt_enable(INT_EPWM3);

    //
    // Enable global Interrupts and higher priority real-time debug events:
    //
    EINT;  // Enable Global interrupt INTM
    ERTM;  // Enable Global realtime interrupt DBGM

    //
    // IDLE loop. Just sit and loop forever (optional):
    //
    for(;;)
    {
        asm ("  NOP");
    }
}

//
// epwm1ISR - EPWM1 ISR to update compare values
//
__interrupt void epwm1ISR(void)
{
    //
    // Update the CMPA and CMPB values
    //
    updateCompare(&epwm1Info);

    //
    // Clear INT flag for this timer
    //
    EPWM_clearEventTriggerInterruptFlag(myEPWM1_BASE);

    //
    // Acknowledge this interrupt to receive more interrupts from group 3
    //
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
}

//
// epwm2ISR - EPWM2 ISR to update compare values
//
__interrupt void epwm2ISR(void)
{
    //
    // Update the CMPA and CMPB values
    //
    if (loop_counter!=AshikFlag)
    {
    updateCompare(&epwm2Info);
    }
    else
    {

        //Ph=300;
        EPWM_selectPeriodLoadEvent(myEPWM2_BASE, EPWM_SHADOW_LOAD_MODE_SYNC);
        EPWM_setPhaseShift(myEPWM2_BASE, Ph); //ashik added Ph
        EPWM_setTimeBaseCounter(myEPWM2_BASE, Ph); //ashik added Ph

    }
    //
    // Clear INT flag for this timer
    //
    EPWM_clearEventTriggerInterruptFlag(myEPWM2_BASE);

    //
    // Acknowledge this interrupt to receive more interrupts from group 3
    //
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
}

//
// epwm3ISR - EPWM3 ISR to update compare values
//
__interrupt void epwm3ISR(void)
{
    //
    // Update the CMPA and CMPB values
    //
    updateCompare(&epwm3Info);

    //
    // Clear INT flag for this timer
    //
    EPWM_clearEventTriggerInterruptFlag(myEPWM3_BASE);

    //
    // Acknowledge this interrupt to receive more interrupts from group 3
    //
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
}

//
// initEPWM1 - Initialize EPWM1 values
//
void initEPWM1()
{
    //
    // Setup TBCLK
    //
    EPWM_setTimeBaseCounterMode(myEPWM1_BASE, EPWM_COUNTER_MODE_UP);
    EPWM_setTimeBasePeriod(myEPWM1_BASE, EPWM1_TIMER_TBPRD);
    EPWM_disablePhaseShiftLoad(myEPWM1_BASE);
    EPWM_setPhaseShift(myEPWM1_BASE, 0U);
    EPWM_setTimeBaseCounter(myEPWM1_BASE, 0U);

    //
    // Set ePWM clock pre-scaler
    //
    EPWM_setClockPrescaler(myEPWM1_BASE,
                           EPWM_CLOCK_DIVIDER_2,
                           EPWM_HSCLOCK_DIVIDER_2);

    //
    // Setup shadow register load on ZERO
    //
    EPWM_setCounterCompareShadowLoadMode(myEPWM1_BASE,
                                         EPWM_COUNTER_COMPARE_A,
                                         EPWM_COMP_LOAD_ON_CNTR_ZERO);
    EPWM_setCounterCompareShadowLoadMode(myEPWM1_BASE,
                                         EPWM_COUNTER_COMPARE_B,
                                         EPWM_COMP_LOAD_ON_CNTR_ZERO);

    //
    // Set Compare values
    //
    EPWM_setCounterCompareValue(myEPWM1_BASE, EPWM_COUNTER_COMPARE_A,
                                EPWM1_MIN_CMPA);
    EPWM_setCounterCompareValue(myEPWM1_BASE, EPWM_COUNTER_COMPARE_B,
                                EPWM1_MIN_CMPB);

    //
    // Set actions for ePWM1A & ePWM1B
    //
    // Set PWM1A on Zero
    EPWM_setActionQualifierAction(myEPWM1_BASE,
                                  EPWM_AQ_OUTPUT_A,
                                  EPWM_AQ_OUTPUT_HIGH,
                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    // Clear PWM1A on event A, up count
    EPWM_setActionQualifierAction(myEPWM1_BASE,
                                  EPWM_AQ_OUTPUT_A,
                                  EPWM_AQ_OUTPUT_LOW,
                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);

    // Set PWM1B on Zero
    EPWM_setActionQualifierAction(myEPWM1_BASE,
                                  EPWM_AQ_OUTPUT_B,
                                  EPWM_AQ_OUTPUT_LOW,
                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    // Clear PWM1B on event B, up count
    EPWM_setActionQualifierAction(myEPWM1_BASE,
                                  EPWM_AQ_OUTPUT_B,
                                  EPWM_AQ_OUTPUT_HIGH,
                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);

//    // Set PWM1B on Zero
//    EPWM_setActionQualifierAction(myEPWM1_BASE,
//                                  EPWM_AQ_OUTPUT_B,
//                                  EPWM_AQ_OUTPUT_HIGH,
//                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
//    // Clear PWM1B on event B, up count
//    EPWM_setActionQualifierAction(myEPWM1_BASE,
//                                  EPWM_AQ_OUTPUT_B,
//                                  EPWM_AQ_OUTPUT_LOW,
//                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);

    //
    // Interrupt where we will change the Compare Values
    //
    EPWM_setInterruptSource(myEPWM1_BASE, EPWM_INT_TBCTR_ZERO);
    EPWM_enableInterrupt(myEPWM1_BASE);
    EPWM_setInterruptEventCount(myEPWM1_BASE, 3U);

   //
   // Information this example uses to keep track
   // of the direction the CMPA/CMPB values are
   // moving, the min and max allowed values and
   // a pointer to the correct ePWM registers
   //

    // Start by increasing CMPA & CMPB
    epwm1Info.epwmCompADirection = EPWM_CMP_UP;
    epwm1Info.epwmCompBDirection = EPWM_CMP_UP;

    // Clear interrupt counter
    epwm1Info.epwmTimerIntCount = 0;
    epwm1Info.ePWMDone = 0;

    // Set base as ePWM1
    epwm1Info.epwmModule = myEPWM1_BASE;

    // Setup min/max CMPA/CMP values
    epwm1Info.epwmMaxCompA = EPWM1_MAX_CMPA;
    epwm1Info.epwmMinCompA = EPWM1_MIN_CMPA;
    epwm1Info.epwmMaxCompB = EPWM1_MAX_CMPB;
    epwm1Info.epwmMinCompB = EPWM1_MIN_CMPB;
}

//
// initEPWM2 - Initialize EPWM2 values
//
void initEPWM2()
{
    //
    // Setup TBCLK
    //
    EPWM_setTimeBaseCounterMode(myEPWM2_BASE, EPWM_COUNTER_MODE_UP);
    EPWM_setTimeBasePeriod(myEPWM2_BASE, EPWM2_TIMER_TBPRD);
    EPWM_disablePhaseShiftLoad(myEPWM2_BASE);
    EPWM_setPhaseShift(myEPWM2_BASE, 0U);
    EPWM_setTimeBaseCounter(myEPWM2_BASE, 0U);

    //
    // Set ePWM clock pre-scaler
    //
    EPWM_setClockPrescaler(myEPWM2_BASE,
                           EPWM_CLOCK_DIVIDER_2,
                           EPWM_HSCLOCK_DIVIDER_2);

    //
    // Setup shadow register load on ZERO
    //
    EPWM_setCounterCompareShadowLoadMode(myEPWM2_BASE,
                                         EPWM_COUNTER_COMPARE_A,
                                         EPWM_COMP_LOAD_ON_CNTR_ZERO);
    EPWM_setCounterCompareShadowLoadMode(myEPWM2_BASE,
                                         EPWM_COUNTER_COMPARE_B,
                                         EPWM_COMP_LOAD_ON_CNTR_ZERO);

    //
    // Set Compare values
    //
    EPWM_setCounterCompareValue(myEPWM2_BASE, EPWM_COUNTER_COMPARE_A,
                                EPWM2_MIN_CMPA);
    EPWM_setCounterCompareValue(myEPWM2_BASE, EPWM_COUNTER_COMPARE_B,
                                EPWM2_MIN_CMPB); //EPWM2_MAX_CMPB

    //
    // Set actions for ePWM1A & ePWM1B
    //
    // Clear PWM2A on period and set on event A, up-count
//    EPWM_setActionQualifierAction(myEPWM2_BASE,
//                                  EPWM_AQ_OUTPUT_A,
//                                  EPWM_AQ_OUTPUT_LOW,
//                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
//    EPWM_setActionQualifierAction(myEPWM2_BASE,
//                                  EPWM_AQ_OUTPUT_A,
//                                  EPWM_AQ_OUTPUT_HIGH,
//                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);

    // Clear PWM2A on period and set on event A, up-count
    EPWM_setActionQualifierAction(myEPWM2_BASE,
                                  EPWM_AQ_OUTPUT_A,
                                  EPWM_AQ_OUTPUT_HIGH,
                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);// EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD
    EPWM_setActionQualifierAction(myEPWM2_BASE,
                                  EPWM_AQ_OUTPUT_A,
                                  EPWM_AQ_OUTPUT_LOW,
                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);

    // Clear PWM2B on Period & set on event B, up-count
    EPWM_setActionQualifierAction(myEPWM2_BASE,
                                  EPWM_AQ_OUTPUT_B,
                                  EPWM_AQ_OUTPUT_LOW,
                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);// EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD
    EPWM_setActionQualifierAction(myEPWM2_BASE,
                                  EPWM_AQ_OUTPUT_B,
                                  EPWM_AQ_OUTPUT_HIGH,
                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);

    //
    // Interrupt where we will change the Compare Values
    //
    EPWM_setInterruptSource(myEPWM2_BASE, EPWM_INT_TBCTR_ZERO);
    EPWM_enableInterrupt(myEPWM2_BASE);
    EPWM_setInterruptEventCount(myEPWM2_BASE, 3U);

    //
    // Information this example uses to keep track
    // of the direction the CMPA/CMPB values are
    // moving, the min and max allowed values and
    // a pointer to the correct ePWM registers
    //

    // Start by increasing CMPA & decreasing CMPB
    epwm2Info.epwmCompADirection = EPWM_CMP_UP;
    epwm2Info.epwmCompBDirection = EPWM_CMP_DOWN;

    // Clear interrupt counter
    epwm2Info.epwmTimerIntCount = 0;

    // Set base as ePWM2
    epwm2Info.epwmModule = myEPWM2_BASE;

    // Setup min/max CMPA/CMP values
    epwm2Info.epwmMaxCompA = EPWM2_MAX_CMPA;
    epwm2Info.epwmMinCompA = EPWM2_MIN_CMPA;
    epwm2Info.epwmMaxCompB = EPWM2_MAX_CMPB;
    epwm2Info.epwmMinCompB = EPWM2_MIN_CMPB;
}

//
// initEPWM3 - Initialize EPWM3 values
//
void initEPWM3(void)
{
    //
    // Setup TBCLK
    //
    EPWM_setTimeBaseCounterMode(myEPWM3_BASE, EPWM_COUNTER_MODE_UP);
    EPWM_setTimeBasePeriod(myEPWM3_BASE, EPWM3_TIMER_TBPRD);
    EPWM_disablePhaseShiftLoad(myEPWM3_BASE);
    EPWM_setPhaseShift(myEPWM3_BASE, 0U);
    EPWM_setTimeBaseCounter(myEPWM3_BASE, 0U);

    //
    // Set ePWM clock pre-scaler
    //
    EPWM_setClockPrescaler(myEPWM3_BASE,
                           EPWM_CLOCK_DIVIDER_1,
                           EPWM_HSCLOCK_DIVIDER_1);

    //
    // Setup shadow register load on ZERO
    //
    EPWM_setCounterCompareShadowLoadMode(myEPWM3_BASE,
                                         EPWM_COUNTER_COMPARE_A,
                                         EPWM_COMP_LOAD_ON_CNTR_ZERO);
    EPWM_setCounterCompareShadowLoadMode(myEPWM3_BASE,
                                         EPWM_COUNTER_COMPARE_B,
                                         EPWM_COMP_LOAD_ON_CNTR_ZERO);

    //
    // Set Compare values
    //
    EPWM_setCounterCompareValue(myEPWM3_BASE, EPWM_COUNTER_COMPARE_A,
                                EPWM3_MIN_CMPA);
    EPWM_setCounterCompareValue(myEPWM3_BASE, EPWM_COUNTER_COMPARE_B,
                                EPWM3_MAX_CMPB);

    //
    // Set actions for ePWM1A & ePWM1B
    //
    // Set PWM3A on event B, up-count & clear on event B, up-count
    EPWM_setActionQualifierAction(myEPWM3_BASE,
                                  EPWM_AQ_OUTPUT_A,
                                  EPWM_AQ_OUTPUT_HIGH,
                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    EPWM_setActionQualifierAction(myEPWM3_BASE,
                                  EPWM_AQ_OUTPUT_A,
                                  EPWM_AQ_OUTPUT_LOW,
                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);

    // Toggle EPWM3B on counter = zero
    EPWM_setActionQualifierAction(myEPWM3_BASE,
                                  EPWM_AQ_OUTPUT_B,
                                  EPWM_AQ_OUTPUT_TOGGLE,
                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);

    //
    // Interrupt where we will change the Compare Values
    //
    EPWM_setInterruptSource(myEPWM3_BASE, EPWM_INT_TBCTR_ZERO);
    EPWM_enableInterrupt(myEPWM3_BASE);
    EPWM_setInterruptEventCount(myEPWM3_BASE, 3U);

   //
   // Information this example uses to keep track
   // of the direction the CMPA/CMPB values are
   // moving, the min and max allowed values and
   // a pointer to the correct ePWM registers
   //

    // Start by increasing CMPA & decreasing CMPB
    epwm3Info.epwmCompADirection = EPWM_CMP_UP;
    epwm3Info.epwmCompBDirection = EPWM_CMP_UP;

    // Start the count at 0
    epwm3Info.epwmTimerIntCount = 0;

    // Set base as ePWM1
    epwm3Info.epwmModule = myEPWM3_BASE;

    // Setup min/max CMPA/CMP values
    epwm3Info.epwmMaxCompA = EPWM3_MAX_CMPA;
    epwm3Info.epwmMinCompA = EPWM3_MIN_CMPA;
    epwm3Info.epwmMaxCompB = EPWM3_MAX_CMPB;
    epwm3Info.epwmMinCompB = EPWM3_MIN_CMPB;
}

//
// updateCompare - Update the compare values for the specified EPWM
//
void updateCompare(epwmInfo *epwm_info)
{
   //
   // Every 10'th interrupt, change the CMPA/CMPB values
   //
   if(epwm_info->epwmTimerIntCount == 10)
   {
       epwm_info->epwmTimerIntCount = 0;
       compAVal = EPWM_getCounterCompareValue(epwm_info->epwmModule,
                                              EPWM_COUNTER_COMPARE_A);
       compBVal = EPWM_getCounterCompareValue(epwm_info->epwmModule,
                                              EPWM_COUNTER_COMPARE_B);
//       if (compAVal==epwm_info->epwmMaxCompA) {epwm1Info.ePWMDone = 1;}
       //
       // If we were increasing CMPA, check to see if
       // we reached the max value.  If not, increase CMPA
       // else, change directions and decrease CMPA
       //
       if(epwm_info->epwmCompADirection == EPWM_CMP_UP)
       {
           if(compAVal < epwm_info->epwmMaxCompA)
           {
               EPWM_setCounterCompareValue(epwm_info->epwmModule,
                                           EPWM_COUNTER_COMPARE_A, ++compAVal);
               AshikFlag = AshikFlag+1;
           }
           else
           {
//               epwm_info->epwmCompADirection = EPWM_CMP_DOWN;
//               EPWM_setCounterCompareValue(epwm_info->epwmModule,
//                                           EPWM_COUNTER_COMPARE_A, --compAVal);
//               epwm1Info.ePWMDone = 1;

           }

       }

       //
       // If we were decreasing CMPA, check to see if
       // we reached the min value.  If not, decrease CMPA
       // else, change directions and increase CMPA
       //
       else
       {
           if(compAVal == epwm_info->epwmMinCompA)
           {
               epwm_info->epwmCompADirection = EPWM_CMP_UP;
               EPWM_setCounterCompareValue(epwm_info->epwmModule,
                                           EPWM_COUNTER_COMPARE_A, ++compAVal);

           }
           else
           {
               EPWM_setCounterCompareValue(epwm_info->epwmModule,
                                           EPWM_COUNTER_COMPARE_A, --compAVal);
           }
       }

       //
       // If we were increasing CMPB, check to see if
       // we reached the max value.  If not, increase CMPB
       // else, change directions and decrease CMPB
       //
       if(epwm_info->epwmCompBDirection == EPWM_CMP_UP)
       {
           if(compBVal < epwm_info->epwmMaxCompB)
           {
               EPWM_setCounterCompareValue(epwm_info->epwmModule,
                                           EPWM_COUNTER_COMPARE_B, ++compBVal);
           }
           else
           {
//               epwm_info->epwmCompBDirection = EPWM_CMP_DOWN;
//               EPWM_setCounterCompareValue(epwm_info->epwmModule,
//                                           EPWM_COUNTER_COMPARE_B, --compBVal);

           }
       }

       //
       // If we were decreasing CMPB, check to see if
       // we reached the min value.  If not, decrease CMPB
       // else, change directions and increase CMPB
       //
       else
       {
           if(compBVal == epwm_info->epwmMinCompB)
           {
               epwm_info->epwmCompBDirection = EPWM_CMP_UP;
               EPWM_setCounterCompareValue(epwm_info->epwmModule,
                                           EPWM_COUNTER_COMPARE_B, ++compBVal);
           }
           else
           {
               EPWM_setCounterCompareValue(epwm_info->epwmModule,
                                           EPWM_COUNTER_COMPARE_B, --compBVal);
           }
       }
   }

   //
   // Increment interrupt count if < 10
   //
   else
   {
      epwm_info->epwmTimerIntCount++;
   }

   return;

}
//
// End of file
//

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

    尊敬的 Ashik:

    对延迟回复深表歉意。

    这个代码片段很长、您能否在代码中标识您关心的特定位置? loop_counter 和 AshikFlag 的作用是什么? 能否提供 EPWM2在较低和较高频率下的示波器截图?

    谢谢!

    Luke

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

    Luke、您好!

    我添加了相关代码。

    我想在 PWM 达到50%占空比后从看门狗分配相移(Ph)。 我不太了解用于确定占空比何时达到50%的直观方法。 这就是为什么在 updateCompare()中,我在第623行中放置了一个标志。 在 epwm2isr()中断函数中,我做了检查(代码片段中给出)。 在将 AshikFlag 的最终值放入 loop_counter 的同时、我可以从看门狗启动 else 循环。

    __interrupt void epwm2ISR(void)
    {
        //
        // Update the CMPA and CMPB values
        //
        if (loop_counter!=AshikFlag)
        {
        updateCompare(&epwm2Info);
        }
        else
        {
    
            //Ph=300;
            EPWM_selectPeriodLoadEvent(myEPWM2_BASE, EPWM_SHADOW_LOAD_MODE_SYNC);
            EPWM_setPhaseShift(myEPWM2_BASE, Ph); //ashik added Ph
            EPWM_setTimeBaseCounter(myEPWM2_BASE, Ph); //ashik added Ph
    
        }
     

    看门狗

    loop_counter==AshikFlag 之前发生的所有事件

     loop_counter==AshikFlag 之后进行映射

    感谢您的帮助。

    Ashik

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

    大家好、Luke、这方面有任何更新吗?

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

    尊敬的 Ashik:

    我假设该示波器屏幕截图从顶部到底部显示了 EPWM1A、EPWM1B、EPWM2A、EPWM2B。 如果不正确、请告诉我。

    Ph 应该是300吗? 我在代码顶部看到 EPWM2_TIMER_TBPRD 为100。 这是否有意为之? 我没有看到任何用于修改 Ph 的代码、它是如何修改的?

    如果相移大于 CMPA 值、将出现错过的动作限定器事件、因为发生相移时、TBCTR 将跳过 CMPA。

    当占空比达到50%时、您对 EPWM2的期望相移是多大?

    输出中的干扰 可能是由于您 在原始代码片段的第262行对 ePWM TBCTR 进行了硬编码所致。 此代码的用途是什么? 仅仅对相移值进行编程以使相移在下一个 ePWM 周期中生效是不够的吗? 由于 ISR 中先前调用的 driverlib 函数的开销、在触发 EPWM2中断和执行此代码之间会有一定的延迟、 因此、执行此代码后、EPWM1和 EPWM2之间的有效相移实际上并不是 Ph。

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

    感谢您的回复 Luke。

    "我假设这个示波器图片从上到下依次显示了 EPWM1A、EPWM1B、EPWM2A、EPWM2B。 如果这是不正确的,请告诉我。"

    -是的,您是正确的。 虽然代码中有 EPWM3、但我目前暂不考虑该 EPWM3。

    "是不是应该是人?" 我在代码顶部看到 EPWM2_TIMER_TBPRD 为100。 这是否有意为之? 我没有看到任何修改 Ph 的代码、它是如何修改的"

    "如果相移大于 CMPA 值、将出现错过的动作限定器事件、因为发生相移时、TBCTR 将跳过 CMPA。"

    -谢谢你指出这一点。 我错了。 时间 EPWM2_TIMER_TBPRD 为100、30度漂移的 Ph 值应为~8。

    -我已将应用 Ph 的逻辑放入_interrupt void epwm2ISR (void)中。  

    __interrupt void epwm2ISR(void)
    {
        //
        // Update the CMPA and CMPB values
        //
        if (loop_counter!=AshikFlag)
        {
        updateCompare(&epwm2Info);
        }
        else
        {
    
            //Ph=300;
            EPWM_selectPeriodLoadEvent(myEPWM2_BASE, EPWM_SHADOW_LOAD_MODE_SYNC);
            EPWM_setPhaseShift(myEPWM2_BASE, Ph); //ashik added Ph
            EPWM_setTimeBaseCounter(myEPWM2_BASE, Ph); //ashik added Ph
    
        }
        //
        // Clear INT flag for this timer
        //
        EPWM_clearEventTriggerInterruptFlag(myEPWM2_BASE);
    
        //
        // Acknowledge this interrupt to receive more interrupts from group 3
        //
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
    }
    

    我正在更新看门狗中的 Ph 值。 若要启用任何相移、loop_counter 变量需要与 AshikFlag 相同、如下图所示。

    "当占空比达到50%时、您期望 EPWM2的相移有多大?"

    -现在我期望它从10-30度的变化

    现在主要问题是、当我 通过使 loop_counter=150从看门狗启用_interrupt void epwm2ISR (void)中的逻辑时、ePWM 会变得不稳定。  

    此代码的目的是在初始不存在相移的半桥中应用 PWM、在达到50%占空比后、它将提供特定的相移。 它在低频下工作(即12.5kHz)。 但在较高频率下、epwm2变得不稳定。

    请您对此发表评论。 谢谢

    Ashik

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

    尊敬的 Ashik:

    为了说明这一点、整个代码块的目的是在 EPWM2达到50%占空比时应用相移:

    ePWM_selectPeriodLoadEvent (myEPWM2_base、ePWM_shadow_load_mode_sync);
    EPWM_setPhaseShift (myEPWM2_base、Ph);//ashik 添加了 Ph
    ePWM_setTimeBaseCounter (myEPWM2_base、Ph);//ashik 添加了 Ph

    可能是我误解了您之前的回复、但我仍然不明白为什么以下代码行是必要的:

    ePWM_setTimeBaseCounter (myEPWM2_base、Ph);//ashik 添加了 Ph

    如果调用 EPWM_setPhaseShift、相移将在下一次 EPWM1 TBCTR = 0时生效、因此不需要调用 EPWM_setTimeBaseCounter 来手动将 EPWM2 TBCTR 设置为与相移相同的值、 并且可能会影响您的同步、尤其是在较高 PWM 频率下、此时 ISR 的执行时间是恒定的。

    如果我有误解、或者为什么需要在 ISR 中调用 ePWM_setTimeBaseCounter、请告诉我。

    谢谢!

    Luke

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

    哇,太棒了 它解决了 EPWM2中的不稳定问题。 我已禁用以下行

    //ePWM_setTimeBaseCounter (myEPWM2_base、Ph);//ashik 添加了 Ph。

    只是另一个查询。

    现在 EPWM2B 从 EPWM2A 的上升沿向左移动。 我想使移位具有双向性。 如果我想把 EPWM2B 直接从 EPWM2A 的上升沿进行移位、您能否建议我应在哪个函数中进行更改?

    衷心感谢您指出我的准则中存在的错误。

    Ashik

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

    尊敬的 Ashik:

    很高兴听到这个问题解决了不稳定问题。 如果您希望在输出的一个边沿上产生延迟、您可以利用死区模块。  如果您需要有关死区模块的一般背景信息、我们在此处提供了一个非常有用的视频:

    https://www.ti.com/video/6304743885001?keyMatch=EPWM%20DEADBAND

    该模块可以延迟其中一个 EPWM 输出的上升沿或下降沿、基本上会将它们移至示波器的右侧。

    如果您有任何进一步的问题、请告诉我。

    谢谢!

    Luke

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

    Luke、您好!

    似乎看门狗在 Ph 变量中给出了一个负值、这会使 EPWM2在右侧移动。 负值转换为无符号整数。

    您能告诉我 F280049C 可以工作的最大频率是多少吗? 如何从代码中检查它?

    我可以在使用的代码中应用 HRPWM 吗?

    感谢您的支持。

     Ashik

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

    Luke、您好!

    您可以为我提供任何参考、以便我可以将 HRPWM 集成到当前代码中?

    Ashik

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

    尊敬的 Ashik:

    C2000Ware 中有使用 HRPWM 的示例、如果您在将这些示例用作在系统中添加 HRPWM 功能的基准时遇到任何问题、敬请告知。

    数据表包含系统中包括 ePWM 时钟在内的各种时钟的最大时钟值、在 F28004x 上、该值为100MHz