主题中讨论的其他器件:C2000WARE
//############################################################################# // // FILE: epwm_ex2_updown_aq.c // // TITLE: ePWM Action Qualifier Module - Using up/down count. // //! \addtogroup driver_example_list //! <h1> ePWM Up Down Count Action Qualifier</h1> //! //! This example configures ePWM1, ePWM2, ePWM3 to produce a 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/down count mode for this example. //! //! View the ePWM1A/B(GPIO0 & GPIO1), ePWM2A/B(GPIO2 &GPIO3) //! and ePWM3A/B(GPIO4 & GPIO5) waveforms on oscilloscope. // //############################################################################# // $TI Release: F2837xD Support Library v3.11.00.00 $ // $Release Date: Sun Oct 4 15:55:24 IST 2020 $ // $Copyright: // Copyright (C) 2013-2020 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" static double angle_gen=0,m1=1,Vrefa=0,Vrefb=0,Vrefc=0; static double Vrefx=0,Vrefy=0,Vrefz=0; double PI = 3.14159265359; static double CLK_count=0; // // Defines // #define EPWM1_TIMER_TBPRD 2500U #define EPWM1_MAX_CMPA 1950U #define EPWM1_MIN_CMPA 50U #define EPWM1_MAX_CMPB 1950U #define EPWM1_MIN_CMPB 50U #define EPWM2_TIMER_TBPRD 2000U #define EPWM2_MAX_CMPA 1950U #define EPWM2_MIN_CMPA 50U #define EPWM2_MAX_CMPB 1950U #define EPWM2_MIN_CMPB 50U #define EPWM3_TIMER_TBPRD 2000U #define EPWM3_MAX_CMPA 950U #define EPWM3_MIN_CMPA 50U #define EPWM3_MAX_CMPB 1950U #define EPWM3_MIN_CMPB 1050U #define EPWM_CMP_UP 1U #define EPWM_CMP_DOWN 0U // // Globals // typedef struct { uint32_t epwmModule; uint16_t epwmCompADirection; uint16_t epwmCompBDirection; uint16_t epwmTimerIntCount; uint16_t epwmMaxCompA; uint16_t epwmMinCompA; uint16_t epwmMaxCompB; uint16_t epwmMinCompB; }epwmInformation; // // Globals to hold the ePWM information used in this example // epwmInformation epwm1Info; epwmInformation epwm2Info; epwmInformation epwm3Info; // // 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(epwmInformation *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(); // // Assign the interrupt service routines to ePWM interrupts // Interrupt_register(INT_EPWM1, &epwm1ISR); Interrupt_register(INT_EPWM2, &epwm2ISR); Interrupt_register(INT_EPWM3, &epwm3ISR); // // Configure GPIO0/1 , GPIO2/3 and GPIO4/5 as ePWM1A/1B, ePWM2A/2B and // ePWM3A/3B pins respectively // GPIO_setPadConfig(0, GPIO_PIN_TYPE_STD); GPIO_setPinConfig(GPIO_0_EPWM1A); GPIO_setPadConfig(1, GPIO_PIN_TYPE_STD); GPIO_setPinConfig(GPIO_1_EPWM1B); GPIO_setPadConfig(2, GPIO_PIN_TYPE_STD); GPIO_setPinConfig(GPIO_2_EPWM2A); GPIO_setPadConfig(3, GPIO_PIN_TYPE_STD); GPIO_setPinConfig(GPIO_3_EPWM2B); GPIO_setPadConfig(4, GPIO_PIN_TYPE_STD); GPIO_setPinConfig(GPIO_4_EPWM3A); GPIO_setPadConfig(5, GPIO_PIN_TYPE_STD); GPIO_setPinConfig(GPIO_5_EPWM3B); GPIO_setPadConfig(29, GPIO_PIN_TYPE_STD); // Enable pullup on GPIO6 GPIO_setDirectionMode(29, GPIO_DIR_MODE_OUT); // GPIO6 = output // // Disable sync(Freeze clock to PWM as well) // SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC); initEPWM1(); initEPWM2(); initEPWM3(); // // Enable sync and clock to PWM // SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC); // // Enable ePWM interrupts // Interrupt_enable(INT_EPWM1); Interrupt_enable(INT_EPWM2); Interrupt_enable(INT_EPWM3); // // Enable Global Interrupt (INTM) and realtime interrupt (DBGM) // EINT; ERTM; // // IDLE loop. Just sit and loop forever (optional): // for(;;) { NOP; } } // // epwm1ISR - ePWM 1 ISR // __interrupt void epwm1ISR(void) { GPIO_togglePin(29); CLK_count++; if (CLK_count==10000) { CLK_count=0; } angle_gen = 2*PI*m1*50*(CLK_count*0.0001); //50Hz Vrefa = m1*1*cos(angle_gen); Vrefb = m1*1*cos(angle_gen - 2*PI/3); Vrefc = m1*1*cos(angle_gen + 2*PI/3); Vrefx = m1*1*cos(angle_gen - PI/6); Vrefy = m1*1*cos(angle_gen - 5*PI/6); Vrefz = m1*1*cos(angle_gen + PI/2); // // Update the CMPA and CMPB values // updateCompare(&epwm1Info); // // Clear INT flag for this timer // EPWM_clearEventTriggerInterruptFlag(EPWM1_BASE); // // Acknowledge interrupt group // Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3); } // // epwm2ISR - ePWM 2 ISR // __interrupt void epwm2ISR(void) { // // Update the CMPA and CMPB values // updateCompare(&epwm2Info); // // Clear INT flag for this timer // EPWM_clearEventTriggerInterruptFlag(EPWM2_BASE); // // Acknowledge interrupt group // Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3); } // // epwm3ISR - ePWM 3 ISR // __interrupt void epwm3ISR(void) { // // Update the CMPA and CMPB values // updateCompare(&epwm3Info); // // Clear INT flag for this timer // EPWM_clearEventTriggerInterruptFlag(EPWM3_BASE); // // Acknowledge interrupt group // Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3); } // // initEPWM1 - Configure ePWM1 // void initEPWM1() { // // Set-up TBCLK // EPWM_setTimeBasePeriod(EPWM1_BASE, EPWM1_TIMER_TBPRD); EPWM_setPhaseShift(EPWM1_BASE, 0U); EPWM_setTimeBaseCounter(EPWM1_BASE, 0U); // // Set Compare values // EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, EPWM1_MIN_CMPA); EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_B, EPWM1_MAX_CMPB); // // Set up counter mode // EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP_DOWN); EPWM_disablePhaseShiftLoad(EPWM1_BASE); EPWM_setClockPrescaler(EPWM1_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1); // // Set up shadowing // EPWM_setCounterCompareShadowLoadMode(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO); EPWM_setCounterCompareShadowLoadMode(EPWM1_BASE, EPWM_COUNTER_COMPARE_B, EPWM_COMP_LOAD_ON_CNTR_ZERO); // // Set actions // EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA); EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA); EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB); EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB); // // Interrupt where we will change the Compare Values // Select INT on Time base counter zero event, // Enable INT, generate INT on 3rd event // EPWM_setInterruptSource(EPWM1_BASE, EPWM_INT_TBCTR_ZERO); EPWM_enableInterrupt(EPWM1_BASE); EPWM_setInterruptEventCount(EPWM1_BASE, 1U); // // 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 // epwm1Info.epwmCompADirection = EPWM_CMP_UP; epwm1Info.epwmCompBDirection = EPWM_CMP_DOWN; epwm1Info.epwmTimerIntCount = 0U; epwm1Info.epwmModule = EPWM1_BASE; epwm1Info.epwmMaxCompA = EPWM1_MAX_CMPA; epwm1Info.epwmMinCompA = EPWM1_MIN_CMPA; epwm1Info.epwmMaxCompB = EPWM1_MAX_CMPB; epwm1Info.epwmMinCompB = EPWM1_MIN_CMPB; } // // initEPWM2 - Configure ePWM2 // void initEPWM2() { // // Set-up TBCLK // EPWM_setTimeBasePeriod(EPWM2_BASE, EPWM2_TIMER_TBPRD); EPWM_setPhaseShift(EPWM2_BASE, 0U); EPWM_setTimeBaseCounter(EPWM2_BASE, 0U); // // Set Compare values // EPWM_setCounterCompareValue(EPWM2_BASE, EPWM_COUNTER_COMPARE_A, EPWM2_MIN_CMPA); EPWM_setCounterCompareValue(EPWM2_BASE, EPWM_COUNTER_COMPARE_B, EPWM2_MIN_CMPB); // // Set-up counter mode // EPWM_setTimeBaseCounterMode(EPWM2_BASE, EPWM_COUNTER_MODE_UP_DOWN); EPWM_disablePhaseShiftLoad(EPWM2_BASE); EPWM_setClockPrescaler(EPWM2_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1); // // Set-up shadowing // EPWM_setCounterCompareShadowLoadMode(EPWM2_BASE, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO); EPWM_setCounterCompareShadowLoadMode(EPWM2_BASE, EPWM_COUNTER_COMPARE_B, EPWM_COMP_LOAD_ON_CNTR_ZERO); // // Set Action qualifier // EPWM_setActionQualifierAction(EPWM2_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA); EPWM_setActionQualifierAction(EPWM2_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB); EPWM_setActionQualifierAction(EPWM2_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO); EPWM_setActionQualifierAction(EPWM2_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD); // // Interrupt where we will change the Compare Values // Select INT on Time base counter zero event, // Enable INT, generate INT on 3rd event // EPWM_setInterruptSource(EPWM2_BASE, EPWM_INT_TBCTR_ZERO); EPWM_enableInterrupt(EPWM2_BASE); EPWM_setInterruptEventCount(EPWM2_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 // epwm2Info.epwmCompADirection = EPWM_CMP_UP; epwm2Info.epwmCompBDirection = EPWM_CMP_UP; epwm2Info.epwmTimerIntCount = 0U; epwm2Info.epwmModule = EPWM2_BASE; epwm2Info.epwmMaxCompA = EPWM2_MAX_CMPA; epwm2Info.epwmMinCompA = EPWM2_MIN_CMPA; epwm2Info.epwmMaxCompB = EPWM2_MAX_CMPB; epwm2Info.epwmMinCompB = EPWM2_MIN_CMPB; } // // initEPWM3 - Configure ePWM3 // void initEPWM3(void) { // // Set-up TBCLK // EPWM_setTimeBaseCounterMode(EPWM3_BASE, EPWM_COUNTER_MODE_UP_DOWN); EPWM_setTimeBasePeriod(EPWM3_BASE, EPWM3_TIMER_TBPRD); EPWM_disablePhaseShiftLoad(EPWM3_BASE); EPWM_setPhaseShift(EPWM3_BASE, 0U); EPWM_setTimeBaseCounter(EPWM3_BASE, 0U); EPWM_setClockPrescaler(EPWM3_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1); // // Set up shadowing // EPWM_setCounterCompareShadowLoadMode(EPWM3_BASE, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO); EPWM_setCounterCompareShadowLoadMode(EPWM3_BASE, EPWM_COUNTER_COMPARE_B, EPWM_COMP_LOAD_ON_CNTR_ZERO); // // Set Compare values // EPWM_setCounterCompareValue(EPWM3_BASE, EPWM_COUNTER_COMPARE_A, EPWM3_MIN_CMPA); EPWM_setCounterCompareValue(EPWM3_BASE, EPWM_COUNTER_COMPARE_B, EPWM3_MAX_CMPB); // // Set actions // EPWM_setActionQualifierAction(EPWM3_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD); EPWM_setActionQualifierAction(EPWM3_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB); EPWM_setActionQualifierAction(EPWM3_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD); EPWM_setActionQualifierAction(EPWM3_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA); // // Interrupt where we will change the Compare Values // Select INT on Time base counter zero event, // Enable INT, generate INT on 3rd event // EPWM_setInterruptSource(EPWM3_BASE, EPWM_INT_TBCTR_ZERO); EPWM_enableInterrupt(EPWM3_BASE); EPWM_setInterruptEventCount(EPWM3_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 // epwm3Info.epwmCompADirection = EPWM_CMP_UP; epwm3Info.epwmCompBDirection = EPWM_CMP_DOWN; epwm3Info.epwmTimerIntCount = 0U; epwm3Info.epwmModule = EPWM3_BASE; epwm3Info.epwmMaxCompA = EPWM3_MAX_CMPA; epwm3Info.epwmMinCompA = EPWM3_MIN_CMPA; epwm3Info.epwmMaxCompB = EPWM3_MAX_CMPB; epwm3Info.epwmMinCompB = EPWM3_MIN_CMPB; } // // updateCompare - Function to update the frequency // void updateCompare(epwmInformation *epwmInfo) { uint16_t compAValue; uint16_t compBValue; compAValue = EPWM_getCounterCompareValue(epwmInfo->epwmModule, EPWM_COUNTER_COMPARE_A); compBValue = EPWM_getCounterCompareValue(epwmInfo->epwmModule, EPWM_COUNTER_COMPARE_B); // // Change the CMPA/CMPB values every 10th interrupt. // if(epwmInfo->epwmTimerIntCount == 10U) { epwmInfo->epwmTimerIntCount = 0U; // // 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(epwmInfo->epwmCompADirection == EPWM_CMP_UP) { if(compAValue < (epwmInfo->epwmMaxCompA)) { EPWM_setCounterCompareValue(epwmInfo->epwmModule, EPWM_COUNTER_COMPARE_A, ++compAValue); } else { epwmInfo->epwmCompADirection = EPWM_CMP_DOWN; EPWM_setCounterCompareValue(epwmInfo->epwmModule, EPWM_COUNTER_COMPARE_A, --compAValue); } } // // 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( compAValue == (epwmInfo->epwmMinCompA)) { epwmInfo->epwmCompADirection = EPWM_CMP_UP; EPWM_setCounterCompareValue(epwmInfo->epwmModule, EPWM_COUNTER_COMPARE_A, ++compAValue); } else { EPWM_setCounterCompareValue(epwmInfo->epwmModule, EPWM_COUNTER_COMPARE_A, --compAValue); } } // // 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(epwmInfo->epwmCompBDirection == EPWM_CMP_UP) { if(compBValue < (epwmInfo->epwmMaxCompB)) { EPWM_setCounterCompareValue(epwmInfo->epwmModule, EPWM_COUNTER_COMPARE_B, ++compBValue); } else { epwmInfo->epwmCompBDirection = EPWM_CMP_DOWN; EPWM_setCounterCompareValue(epwmInfo->epwmModule, EPWM_COUNTER_COMPARE_B, --compBValue); } } // // 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(compBValue == (epwmInfo->epwmMinCompB)) { epwmInfo->epwmCompBDirection = EPWM_CMP_UP; EPWM_setCounterCompareValue(epwmInfo->epwmModule, EPWM_COUNTER_COMPARE_B, ++compBValue); } else { EPWM_setCounterCompareValue(epwmInfo->epwmModule, EPWM_COUNTER_COMPARE_B, --compBValue); } } } else { epwmInfo->epwmTimerIntCount++; } }
这是使用库的"ti\c2000\C2000Ware_3_03_00_00\driverlib\f2837xd\examples\CPU1\ePWM"的示例代码。
唯一完成的更改是在 EPWM1ISR 中:
__interrupt void epwm1ISR(void)
{
GPIO_togglePin(29);
CLK_count++;
if (CLK_count==10000)
{
CLK_count=0;
}
angle_gen = 2*PI*m1*50*(CLK_count*0.0001); //50Hz
Vrefa = m1*1*cos(angle_gen);
Vrefb = m1*1*cos(angle_gen - 2*PI/3);
Vrefc = m1*1*cos(angle_gen + 2*PI/3);
Vrefx = m1*1*cos(angle_gen - PI/6);
Vrefy = m1*1*cos(angle_gen - 5*PI/6);
Vrefz = m1*1*cos(angle_gen + PI/2);
//
// Update the CMPA and CMPB values
//
updateCompare(&epwm1Info);
//
// Clear INT flag for this timer
//
EPWM_clearEventTriggerInterruptFlag(EPWM1_BASE);
//
// Acknowledge interrupt group
//
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
}
移除 cos 函数会将 GPIO 切换频率恢复为10kHz、而通过添加 cos 函数、切换频率会降至1.94Khz。
我尝试了相同的代码、进行了逐位操作、而不是函数、这是正常的。
我使用 launchpad 2806x 尝试了同样的东西、也可以正常工作。
但是、一旦我使用函数、就会出现此问题。