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.
大家好!
我正在使用代码 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