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.
PWM配置:
PWM2 UP_DOWN模式,ZERO 时 SET ,PRD 时 CLR,固定50%带死区占空比输出,在 CTR=0 时发出同步信号;
PWM3 UP_DOWN模式,ZERO 时 SET ,PRD 时 CLR,固定50%带死区占空比输出;
PWM3 相对于 PWM2 进行移相,移相值固定在Phase = PRD * 0.98 范围.(0.98是为了让移相小于周期值)
timer2 产生100k的频率中断:
中断内按固定步长改变PRD值(改变PWM频率),相应地计算出新的移相值,保证PWM3和PWM的相位不变。
开启Global Load功能:
PWM2 PRD在ZERO点 由shadow载入active
PWM3 PRD在同步信号输入点 由shadow载入active
PWM3 的Phase移相值和Global Load无关,应该在同步信号输入点 由shadow载入active。
问题:
运行过程中 PWM3 会概率性出现 一个周期3A全高 3B全低的现象。
为了方便TI支持人员调试,我在C:\ti\c2000\C2000Ware_3_04_00_00\driverlib\f28004x\examples\epwm\epwm_ex3_synchronization工程上进行问题复现,只对epwm_ex3_synchronization.c进行修改
但是我不知道怎样传文件上来。如果需要复现问题,请告诉我上传的方法。
下面时问题波形:
请帮我验证一下,谢谢。
有可能跟你之前提问的一个问题相同,跟加载点有关。A高B低是开启了互补模式吗?。上传文件的话,发帖的时候似乎可以直接将文件拖进文本框里面,或者选择“插入”里面有“图片/视频/文件”选项。
之前提到的问题是因为移相值和CMP值接近时,会导致CMP点的AQ EVENT丢失。这个方案我就是避开了移相值和AQ EVENT的位置。
你可以先测试一下我的代码,然后看看问题是什么,有什么解决方案。把我的文件替换C:\ti\c2000\C2000Ware_3_04_00_00\driverlib\f28004x\examples\epwm\epwm_ex3_synchronization中的文件epwm_ex3_synchronization.c就可以看到问题现象了。
谢谢
不好意思,这两天浏览器出问题一直不能登录TI的网站。我就是直接拉到回复框的,看见一个复制的+号然后松手。怎么没有传上来呢,要是传上来了,我能看得见吗?
通过“插入”里选择“图片/视频/文件”进行上传时,我选择双击了我的.c后,选择框里还是说什么都没选,不知道出什么问题了。
我直接插入代码吧,你拷贝一下行吗?
//############################################################################# // // FILE: epwm_ex3_synchronization.c // // TITLE: ePWM Using The Synch Chain and Phase Shift. // //! \addtogroup driver_example_list //! <h1>ePWM Synchronization</h1> //! //! This example configures ePWM1, ePWM2, ePWM3 and ePWM4 as follows //! - ePWM1 without phase shift as master //! - ePWM2 with phase shift of 300 TBCLKs //! - ePWM3 with phase shift of 600 TBCLKs //! - ePWM4 with phase shift of 900 TBCLKs //! //! \b External \b Connections \n //! - GPIO0 EPWM1A //! - GPIO1 EPWM1B //! - GPIO2 EPWM2A //! - GPIO3 EPWM2B //! - GPIO4 EPWM3A //! - GPIO5 EPWM3B //! - GPIO6 EPWM4A //! - GPIO7 EPWM4B //! //! \b Watch \b Variables \n //! - None. // //############################################################################# // $TI Release: F28004x Support Library v1.12.00.00 $ // $Release Date: Fri Feb 12 18:57:27 IST 2021 $ // $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" #define EPWM_TIMER_TBPRD_MAX ((float32_t)277.0) // 180kHz // // Function Prototypes // void initEPWM(uint32_t base); __interrupt void Timer2ISR(void); __interrupt void epwm2ISR(void); __interrupt void epwm3ISR(void); __interrupt void epwm4ISR(void); // // 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); //Interrupt_register(INT_EPWM4, &epwm4ISR); // add Timer Interrupt Interrupt_register(INT_TIMER2, &Timer2ISR); // Initialize timer period to maximum CPUTimer_setPeriod(CPUTIMER2_BASE, DEVICE_SYSCLK_FREQ/100000 ); // 100KHz // Initialize pre-scale counter to divide by 1 (SYSCLKOUT) CPUTimer_setPreScaler(CPUTIMER2_BASE, 0); // Make sure timer is stopped CPUTimer_stopTimer(CPUTIMER2_BASE); CPUTimer_setEmulationMode(CPUTIMER2_BASE, CPUTIMER_EMULATIONMODE_STOPAFTERNEXTDECREMENT); // Reload all counter register with period value CPUTimer_reloadTimerCounter(CPUTIMER2_BASE); // Restart timer CPUTimer_resumeTimer(CPUTIMER2_BASE); // // Configure GPIO0/1 , GPIO2/3 and GPIO4/5 and GPIO6/7 as // ePWM1A/1B, ePWM2A/2B, ePWM3A/3B, ePWM4A/4B pins respectively // Board_init(); // Disable sync(Freeze clock to PWM as well). GTBCLKSYNC is applicable // only for multiple core devices. Uncomment the below statement if // applicable. // // SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_GTBCLKSYNC); SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC); // // Initialize PWM1 without phase shift as master // //initEPWM(myEPWM1_BASE); // // Initialize PWM2 with phase shift of 300 TBCLKs // initEPWM(myEPWM2_BASE); // // Initialize PWM3 with phase shift of 600 TBCLKs // initEPWM(myEPWM3_BASE); EPWM_enablePhaseShiftLoad(myEPWM3_BASE); EPWM_setPhaseShift(myEPWM3_BASE, 274); EPWM_setDeadBandOutputSwapMode(myEPWM3_BASE, EPWM_DB_OUTPUT_A, 1); EPWM_setDeadBandOutputSwapMode(myEPWM3_BASE, EPWM_DB_OUTPUT_B, 1); // // Initialize PWM4 with phase shift of 900 TBCLKs // //initEPWM(myEPWM4_BASE); //EPWM_selectPeriodLoadEvent(myEPWM4_BASE, EPWM_SHADOW_LOAD_MODE_SYNC); //EPWM_setPhaseShift(myEPWM4_BASE, 900); //EPWM_setTimeBaseCounter(myEPWM4_BASE, 900); // // ePWM1 SYNCO is generated on CTR=0// // //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_COUNTER_ZERO); EPWM_setSyncOutPulseMode(myEPWM3_BASE, EPWM_SYNC_OUT_PULSE_DISABLED); // PWM LINK EPWM_setupEPWMLinks(myEPWM3_BASE, EPWM_LINK_WITH_EPWM_2, EPWM_LINK_TBPRD); // Global Load EPWM_enableGlobalLoad(myEPWM2_BASE); EPWM_enableGlobalLoad(myEPWM3_BASE); EPWM_setGlobalLoadEventPrescale(myEPWM2_BASE, 1); EPWM_setGlobalLoadEventPrescale(myEPWM3_BASE, 1); EPWM_enableGlobalLoadRegisters(myEPWM2_BASE, EPWM_GL_REGISTER_TBPRD_TBPRDHR); EPWM_enableGlobalLoadRegisters(myEPWM3_BASE, EPWM_GL_REGISTER_TBPRD_TBPRDHR); EPWM_setGlobalLoadTrigger(myEPWM2_BASE, EPWM_GL_LOAD_PULSE_CNTR_ZERO); EPWM_setGlobalLoadTrigger(myEPWM3_BASE, EPWM_GL_LOAD_PULSE_SYNC); // // 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); //EPWM_enablePhaseShiftLoad(myEPWM3_BASE); //EPWM_enablePhaseShiftLoad(myEPWM4_BASE); // // 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); //Interrupt_enable(INT_EPWM4); Interrupt_enable(INT_TIMER2); CPUTimer_enableInterrupt(CPUTIMER2_BASE); // // Enable Global Interrupt (INTM) and realtime interrupt (DBGM) // EINT; ERTM; // // IDLE loop. Just sit and loop forever (optional): // for(;;) { } } // // epwm1ISR - ePWM 1 ISR // uint16_t uiCntrDirc = 0; uint16_t uiPRDTicks = 0; uint16_t uiPhasTicks = 0; float32_t fPRD_pu = 0.6; float32_t fPhas_pu = 0.0; __interrupt void Timer2ISR(void) { // // Clear INT flag for this timer // EPWM_clearEventTriggerInterruptFlag(myEPWM1_BASE); if(uiCntrDirc == 0) { fPRD_pu += 0.01; if(fPRD_pu >= 0.7) // 257k Hz { uiCntrDirc = 1; } } else { fPRD_pu -= 0.01; if(fPRD_pu <= 0.6) // 300k Hz { uiCntrDirc = 0; } } uiPRDTicks = (uint16_t)(fPRD_pu * EPWM_TIMER_TBPRD_MAX); //fPhas_pu = ((float32_t)uiPRDTicks * 0.98); uiPhasTicks = (uint16_t)((float32_t)uiPRDTicks * 0.98); HWREGH(myEPWM2_BASE + HRPWM_O_TBPRD) = uiPRDTicks; HWREGH(myEPWM3_BASE + HRPWM_O_TBPHS + 1) = uiPhasTicks; // // Acknowledge interrupt group // Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3); } // // epwm2ISR - ePWM 2 ISR // __interrupt void epwm2ISR(void) { // // Clear INT flag for this timer // EPWM_clearEventTriggerInterruptFlag(myEPWM2_BASE); // // Acknowledge interrupt group // Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3); //GLDMODE = 0xF gfrcld //EPWM_forceGlobalLoadOneShotEvent(myEPWM2_BASE); //GLDMODE = 0x3 syncevt //EPWM_setGlobalLoadOneShotLatch(myEPWM2_BASE); } // // epwm3ISR - ePWM 3 ISR // __interrupt void epwm3ISR(void) { // // Clear INT flag for this timer // EPWM_clearEventTriggerInterruptFlag(myEPWM3_BASE); // // Acknowledge interrupt group // Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3); } // // epwm4ISR - ePWM 4 ISR // __interrupt void epwm4ISR(void) { // // Clear INT flag for this timer // EPWM_clearEventTriggerInterruptFlag(myEPWM4_BASE); // // Acknowledge interrupt group // Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3); } void initEPWM(uint32_t base) { // // Set-up TBCLK // EPWM_setTimeBasePeriod(base, EPWM_TIMER_TBPRD_MAX); EPWM_setPhaseShift(base, 0U); EPWM_setTimeBaseCounter(base, 0U); // // Set Compare values // //EPWM_setCounterCompareValue(base, // EPWM_COUNTER_COMPARE_A, // EPWM_TIMER_TBPRD/2); //EPWM_setCounterCompareValue(base, // EPWM_COUNTER_COMPARE_B, // EPWM_TIMER_TBPRD/4); // // Set up counter mode // EPWM_setTimeBaseCounterMode(base, EPWM_COUNTER_MODE_UP_DOWN); EPWM_disablePhaseShiftLoad(base); EPWM_setClockPrescaler(base, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1); // // Set up shadowing // EPWM_setCounterCompareShadowLoadMode(base, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO); EPWM_setCounterCompareShadowLoadMode(base, EPWM_COUNTER_COMPARE_B, EPWM_COMP_LOAD_ON_CNTR_ZERO); // // Set actions // EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO); //EPWM_setActionQualifierAction(base, // EPWM_AQ_OUTPUT_B, // EPWM_AQ_OUTPUT_HIGH, // EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO); EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD); //EPWM_setActionQualifierAction(base, // EPWM_AQ_OUTPUT_B, // EPWM_AQ_OUTPUT_LOW, // EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB); // DB Config EPWM_setDeadBandDelayMode(base, EPWM_DB_RED, true); EPWM_setDeadBandDelayMode(base, EPWM_DB_FED, true); EPWM_setRisingEdgeDeadBandDelayInput(base, 0); EPWM_setFallingEdgeDeadBandDelayInput(base, 0); EPWM_setDeadBandDelayPolarity(base, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW);//DB FED output is inverted EPWM_setDeadBandDelayPolarity(base, EPWM_DB_RED, EPWM_DB_POLARITY_ACTIVE_HIGH); HWREG(base + HRPWM_O_DBFEDHR) = 20; HWREG(base + HRPWM_O_DBREDHR) = 20; // // Interrupt where we will change the Compare Values // Select INT on Time base counter zero event, // Enable INT, generate INT on 1rd event // //EPWM_setInterruptSource(base, EPWM_INT_TBCTR_ZERO); //EPWM_enableInterrupt(base); //EPWM_setInterruptEventCount(base, 1U); }
你好,请问一下你这边测试的时候出现问题的概率大概是多少?一般在什么位置复现的概率比较大?
我这边不知道是示波器设置问题还是其他什么,几次下来没有成功复现。
另外有设置过代码输出格式吗?EABI还是COFF?
你好
是在不好意思,我刚才测试了一下传上来的代码确实不能复现(因为我后来有更改),请将代码的293和295行替换为下面两行代码,就能复现了。
fPhas_pu = ((float32_t)fPRD_pu * 0.98);
uiPhasTicks = (uint16_t)((float32_t)fPhas_pu * EPWM_TIMER_TBPRD_MAX);
你示波器要用触发模式,触发条件PWM3B正脉冲宽度大于3us.
实在抱歉,我的疏忽,浪费你宝贵的时间,还得麻烦你从测试一遍。
你好,今天在实验室测试了一下,使用的是launchPAD,脉冲触发3us的情况,但是没看到类似现象。
我发了一个E2E帖子,看看美国那边的工程师是否能测试到或者看看能否发现代码方面的问题。你可以留意一下这个帖子以及看看有什么需要补充的吗:
e2e.ti.com/.../tms320f280049c-variable-frequency-phase-shift-control-of-pwm