Thread 中讨论的其他器件:SysConfig
尊敬的 C2000专家:
我想使用高分辨率死区、但您能分享一个如何配置高分辨率死区的示例吗?
此致、
插孔
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.
尊敬的 C2000专家:
我想使用高分辨率死区、但您能分享一个如何配置高分辨率死区的示例吗?
此致、
插孔
尊敬的 Jack:
虽然我无法找到高分辨率死区(HR DB)示例项目、 但器 件的 TRM 第17.15.1.4节讨论了可用于 HR DB 的设置、而第17.15.1.6节提供了有关如何正确使用这些设置的具体书面示例。
此外、SysConfig 工具提供对这些值的广泛、直观的操作-我建议将这些设置与 TRM 的示例结合使用、以了解各种函数与所讨论的设置之间的关系。
此致、
Jason Osborn
您好 Jason、
我打算在 TI.com 上下载 SysConfig 工具、一开始很好、但10%后失败。
回到 WEBAND 高分辨率问题、我认为我已经按照 TRM 中的建议进行了配置、但仍然无法在 EPWM1B 上获得高分辨率、我可以在 EPWM1A 上获得高分辨率。 以下是寄存器的值、您能不能帮助分析我无法得到它的原因吗?
1. DBCTL 寄存器值

2. HRCNFG2寄存器的值

3、HRCNFG

4.使用向上/向下计数模式
5. DBRED DBREDHR DBFED DBFEDHR

尊敬的 Jack:
对迟迟不答复表示歉意! 根据此主题、您选择的 DBCTL.POLSEL 寄存器(即 EPWMxB 反相)将导致 EPWMxB 上出现非 HR 输出。 我建议将该值设置为0、并查看如何利用 HRCNFG.SELOUTB 寄存器位以高分辨率复制该行为。 此外、如果您尝试实现其他 DB 功能、请在查看典型死区控制之前仔细查看高分辨率控制寄存器-许多死区功能在没有进一步配置的情况下无法完全用于高分辨率、或者完全被替换。
希望尽管延迟了、但这会有所帮助、
Jason Osborn
您好 Jason、
我在下面插入了我的 C 代码、以帮助您重现高分辨率问题、您能帮您看看吗? 谢谢。。。
//############################################################################# // // FILE: hrpwm_ex4_duty_updown_sfo.c // // TITLE: HRPWM Duty Control with UPDOWN Mode. // //! \addtogroup driver_example_list //! <h1>HRPWM Duty Control with UPDOWN Mode</h1> //! //! This example calls the following TI's MEP Scale Factor Optimizer (SFO) //! software library V8 functions: //! //! \b int \b SFO(); \n //! - updates MEP_ScaleFactor dynamically when HRPWM is in use //! - updates HRMSTEP register (exists only in EPwm1Regs register space) //! with MEP_ScaleFactor value //! - returns 2 if error: MEP_ScaleFactor is greater than maximum value of 255 //! (Auto-conversion may not function properly under this condition) //! - returns 1 when complete for the specified channel //! - returns 0 if not complete for the specified channel //! //! This example is intended to explain the HRPWM capabilities. The code can be //! optimized for code efficiency. Refer to TI's Digital power application //! examples and TI Digital Power Supply software libraries for details. //! //! \b External \b Connections \n //! - Monitor ePWM1/2/3/4 A/B pins on an oscilloscope. // //############################################################################# // // $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 "board.h" #include "sfo_v8.h" /*----------------------------------------------------------------------------- Define the structure of the PWM Driver Object -----------------------------------------------------------------------------*/ typedef struct { uint16_t PeriodMax; // Parameter: PWM Half-Period in CPU clock cycles (Q0) uint16_t HalfPerMax; // Parameter: Half of PeriodMax (Q0) uint16_t Deadband; // Parameter: PWM deadband in CPU clock cycles (Q0) } PWMGEN ; #define CHANNEL_B_AS_ZRO_PRD_REF 1 #define EPWM_TIMER_TBPRD 100UL #define MIN_HRPWM_DUTY_PERCENT 4.0/((float32_t)EPWM_TIMER_TBPRD)*100.0 // // Defines // #define LAST_EPWM_INDEX_FOR_EXAMPLE 5 #define DEADTIME_ARED (50.752f) /* ns */ #define DEADTIME_BFED (50.752f) /* ns */ #define SW_FREQ (300.0) /* Khz */ #define PWM_PERIOD ((uint32_t)(DEVICE_SYSCLK_FREQ/(SW_FREQ*1000.0))) //PERIOD // // Globals // float32_t dutyFine = 50.0; uint16_t status; int MEP_ScaleFactor; // Global variable used by the SFO library // Result can be used for all HRPWM channels // This variable is also copied to HRMSTEP // register by SFO() function. PWMGEN pwm; volatile uint32_t ePWM[] = {EPWM1_BASE, EPWM1_BASE, EPWM2_BASE, EPWM3_BASE, EPWM4_BASE}; // // Function Prototypes // void initHRPWM_ChannelB(uint32_t period); void error(void); //__interrupt void epwm1ISR(void); //__interrupt void epwm2ISR(void); //__interrupt void epwm3ISR(void); //__interrupt void epwm4ISR(void); void init_epwm(void); // // Main // void main(void) { uint16_t i = 0; // // 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); // // Calling SFO() updates the HRMSTEP register with calibrated MEP_ScaleFactor. // HRMSTEP must be populated with a scale factor value prior to enabling // high resolution period control. // while(status == SFO_INCOMPLETE) { status = SFO(); if(status == SFO_ERROR) { error(); // SFO function returns 2 if an error occurs & # of MEP } // steps/coarse step exceeds maximum of 255. } // // Disable sync(Freeze clock to PWM as well) // SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC); init_epwm(); // // Initialize the EPWM GPIOs and change XBAR inputs from using GPIO0 // //Board_init(); //initHRPWM_ChannelB(EPWM_TIMER_TBPRD); // // 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); // // Enable Global Interrupt (INTM) and realtime interrupt (DBGM) // EINT; ERTM; for(;;) { // // Sweep DutyFine // for(dutyFine = MIN_HRPWM_DUTY_PERCENT; dutyFine < (100.0-MIN_HRPWM_DUTY_PERCENT); dutyFine += 0.0001) { DEVICE_DELAY_US(100); for(i=1; i<LAST_EPWM_INDEX_FOR_EXAMPLE; i++) { float32_t count = ((100.0 - dutyFine) * (float32_t)(pwm.HalfPerMax << 8))/100.0; uint32_t compCount = (count); uint32_t hrCompCount = (compCount & (0x000000FF)); if (hrCompCount == 0) { // // Add 1 to not have CMPxHR = 0 // compCount |= 0x00000001; } HRPWM_setCounterCompareValue(EPWM1_BASE, HRPWM_COUNTER_COMPARE_A, compCount); #if CHANNEL_B_AS_ZRO_PRD_REF == 0 HRPWM_setCounterCompareValue(EPWM1_BASE, HRPWM_COUNTER_COMPARE_B, compCount); #endif } // // Call the scale factor optimizer lib function SFO() // periodically to track for any change due to temp/voltage. // This function generates MEP_ScaleFactor by running the // MEP calibration module in the HRPWM logic. This scale // factor can be used for all HRPWM channels. The SFO() // function also updates the HRMSTEP register with the // scale factor value. // status = SFO(); // in background, MEP calibration module // continuously updates MEP_ScaleFactor if (status == SFO_ERROR) { error(); // SFO function returns 2 if an error occurs & # // of MEP steps/coarse step } // exceeds maximum of 255. } } } void init_epwm(void) { pwm.PeriodMax = PWM_PERIOD; pwm.HalfPerMax=pwm.PeriodMax>>1; pwm.Deadband = 0; /************************* EPWM1 CONFIGURATION ************************/ /* 0. force EPWM1A and EPWM1B continuous low */ EPWM_setActionQualifierContSWForceAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_SW_OUTPUT_LOW); EPWM_setActionQualifierContSWForceAction(EPWM1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_SW_OUTPUT_LOW); EPWM_setActionQualifierContSWForceShadowMode(EPWM1_BASE, EPWM_AQ_SW_SH_LOAD_ON_CNTR_PERIOD); EPWM_setActionQualifierShadowLoadMode(EPWM1_BASE, EPWM_ACTION_QUALIFIER_A, EPWM_AQ_LOAD_ON_CNTR_PERIOD); EPWM_setActionQualifierShadowLoadMode(EPWM1_BASE, EPWM_ACTION_QUALIFIER_B, EPWM_AQ_LOAD_ON_CNTR_PERIOD); EPWM_setDeadBandControlShadowLoadMode(EPWM1_BASE, EPWM_DB_LOAD_ON_CNTR_PERIOD); EPWM_setRisingEdgeDelayCountShadowLoadMode(EPWM1_BASE, EPWM_RED_LOAD_ON_CNTR_PERIOD); EPWM_setFallingEdgeDelayCountShadowLoadMode(EPWM1_BASE, EPWM_FED_LOAD_ON_CNTR_PERIOD); #ifdef GLDEN EPWM_enableGlobalLoad(EPWM1_BASE); EPWM_setGlobalLoadTrigger(EPWM1_BASE, EPWM_GL_LOAD_PULSE_CNTR_PERIOD); EPWM_setGlobalLoadEventPrescale(EPWM1_BASE, 1); EPWM_enableGlobalLoadRegisters(EPWM1_BASE, 0xFFFF); #endif /* 1. Set-up TBCLK */ EPWM_setTimeBasePeriod(EPWM1_BASE, pwm.HalfPerMax); EPWM_setPhaseShift(EPWM1_BASE, 0U); EPWM_disablePhaseShiftLoad(EPWM1_BASE); EPWM_setTimeBaseCounter(EPWM1_BASE, 0U); EPWM_enableSyncOutPulseSource(EPWM1_BASE, EPWM_SYNC_OUT_PULSE_ON_CNTR_ZERO); /* 2. Set Compare values */ EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, 2); EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_B, 0); EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_C, pwm.HalfPerMax); EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_D, (pwm.HalfPerMax - 30)); /* 3. Set up counter mode */ EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP_DOWN); EPWM_setClockPrescaler(EPWM1_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1); /* 4. Set up shadowing */ EPWM_setCounterCompareShadowLoadMode(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO_PERIOD); EPWM_setCounterCompareShadowLoadMode(EPWM1_BASE, EPWM_COUNTER_COMPARE_B, EPWM_COMP_LOAD_ON_CNTR_ZERO_PERIOD); /* 5. 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_CMPA); EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA); /* 6. DBCTL */ EPWM_setDeadBandDelayMode(EPWM1_BASE,EPWM_DB_RED,true); EPWM_setDeadBandDelayMode(EPWM1_BASE,EPWM_DB_FED,true); EPWM_setDeadBandDelayPolarity(EPWM1_BASE,EPWM_DB_RED,EPWM_DB_POLARITY_ACTIVE_HIGH); EPWM_setDeadBandDelayPolarity(EPWM1_BASE,EPWM_DB_FED,EPWM_DB_POLARITY_ACTIVE_HIGH); EPWM_setRisingEdgeDeadBandDelayInput(EPWM1_BASE, EPWM_DB_INPUT_EPWMA); EPWM_setFallingEdgeDeadBandDelayInput(EPWM1_BASE, EPWM_DB_INPUT_EPWMA); EPWM_setDeadBandControlShadowLoadMode(EPWM1_BASE,EPWM_DB_LOAD_ON_CNTR_ZERO_PERIOD); EPWM_setRisingEdgeDelayCountShadowLoadMode(EPWM1_BASE,EPWM_RED_LOAD_ON_CNTR_ZERO_PERIOD); EPWM_setFallingEdgeDelayCountShadowLoadMode(EPWM1_BASE,EPWM_FED_LOAD_ON_CNTR_ZERO_PERIOD); EPWM_setDeadBandCounterClock(EPWM1_BASE,EPWM_DB_COUNTER_CLOCK_HALF_CYCLE); //HWREGH(EPWM1_BASE + EPWM_O_DBCTL) = BUCKON_DBCTL; //HWREGH(EPWM1_BASE + EPWM_O_DBCTL2) = BUCK_DBCTL2; //EPWM_setActionQualifierContSWForceAction(EPWM1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_SW_OUTPUT_HIGH); /* 7. RED and FED config */ /* Half cycle enable delay count calculation */ { float32_t dbred_time = DEADTIME_ARED; float32_t dbfed_time = DEADTIME_BFED; float32_t tbclkPeriod = (1e9/DEVICE_SYSCLK_FREQ); uint32_t dbred_count = (dbred_time * 2.0f) / tbclkPeriod; uint32_t dbfed_count = (dbfed_time * 2.0f) / tbclkPeriod; EPWM_setRisingEdgeDelayCount(EPWM1_BASE, dbred_count); EPWM_setFallingEdgeDelayCount(EPWM1_BASE,dbfed_count); //HWREG(EPWM1_BASE + EPWM_O_DBRED) = dbred_count; //HWREG(EPWM1_BASE + EPWM_O_DBFED) = dbfed_count; } HRPWM_setMEPEdgeSelect(EPWM1_BASE, HRPWM_CHANNEL_A, HRPWM_MEP_CTRL_RISING_AND_FALLING_EDGE); HRPWM_setMEPControlMode(EPWM1_BASE, HRPWM_CHANNEL_A, HRPWM_MEP_DUTY_PERIOD_CTRL); /* * Set up shadowing * MUST BE CTR=(ZER & PRD) */ HRPWM_setCounterCompareShadowLoadEvent(EPWM1_BASE, HRPWM_CHANNEL_A, HRPWM_LOAD_ON_CNTR_ZERO_PERIOD); HRPWM_setMEPEdgeSelect(EPWM1_BASE, HRPWM_CHANNEL_B, HRPWM_MEP_CTRL_RISING_AND_FALLING_EDGE); HRPWM_setMEPControlMode(EPWM1_BASE, HRPWM_CHANNEL_B, HRPWM_MEP_DUTY_PERIOD_CTRL); /* * Set up shadowing * MUST BE CTR=(ZER & PRD) */ HRPWM_setCounterCompareShadowLoadEvent(EPWM1_BASE, HRPWM_CHANNEL_B, HRPWM_LOAD_ON_CNTR_ZERO_PERIOD); HRPWM_setDeadbandMEPEdgeSelect(EPWM1_BASE, HRPWM_DB_MEP_CTRL_RED_FED); HRPWM_setRisingEdgeDelayLoadMode(EPWM1_BASE, HRPWM_LOAD_ON_CNTR_ZERO_PERIOD); HRPWM_setFallingEdgeDelayLoadMode(EPWM1_BASE, HRPWM_LOAD_ON_CNTR_ZERO_PERIOD); HRPWM_enableAutoConversion(EPWM1_BASE); HRPWM_enablePeriodControl(EPWM1_BASE); HRPWM_enablePhaseShiftLoad(EPWM1_BASE); EPWM_setActionQualifierContSWForceAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_SW_DISABLED); EPWM_setActionQualifierContSWForceAction(EPWM1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_SW_DISABLED); GPIO_setPinConfig(GPIO_0_EPWM1_A); GPIO_setPinConfig(GPIO_1_EPWM1_B); } // // error - Halt debugger when called // void error (void) { ESTOP0; // Stop here and handle error }
尊敬的 Jack:
一个澄清问题。 您的代码当前已设置、这样 ePWMxB 的最终输出将通过馈送调整的 ePWMxA 而不是 AQ 的 ePWMxB 输出(即 AQ 对 ePWMxB 所做的任何操作都不会对最终输出产生任何影响)根据生成
EPWM_setFallingEdgeDeadBandDelayInput(EPWM1_BASE, EPWM_DB_INPUT_EPWMA);
是这样吗? 这应该意味 着 ePWMxB 与 ePWMxA 完全一样、但使用馈送而不是红色。 如果这不是您看到的、您能否提供您在 GPIO 引脚上看到的波形?
此致、
Jason Osborn
您好 Jason、
感谢您在这里的努力、很抱歉我推迟了。
实际上、我需要的是 EPWM1B 与 EPWM1A 互补、具有一定的死区时间、但无法在 EPWM1B 上获得高分辨率。
因此、在我的测试代码中、为了找出是什么使 EPWM1B 没有高分辨率。 我使用相同的源(EPWMA)配置 FE 和 RE 的输入、只是使用不同的 FED 和红色。 因此、您的理解是正确的。 ("这应意味 着 ePWMxB 与 ePWMxA 相同、但使用馈送而不是红色。")
在我的测试代码中、占空比随着速度的极慢而增加和减少。 在波形中、我可以看到 EPWM1A 以精细步长增加/减少、但 EPWM1B 上存在粗略步长(10ns 步长)增加/减少。 这可以使用我的代码轻松进行测试。
在这里、我需要您和您的团队支持来了解如何将 EPWM1B 配置为具有使用死区的高分辨率。 如果我的测试代码中缺少任何内容、请更正。 谢谢。。。
此致、
插孔
插孔、
好的。 我 在测试时了解到 、我们似乎都忽略了一些东西... 这一点很重要。
第80行
#define CHANNEL_B_AS_ZRO_PRD_REF 1
请将其更改为
#define CHANNEL_B_AS_ZRO_PRD_REF 0
此致、
Jason Osborn
(为了准确起见、我返回并检查了是否改变 POLSEL 的值是否影响了 HRPWM 的功能。 据我所知、在此版本的4类 HRPWM 中、POLSEL 对 HRPWM 没有任何影响。)
您好 Jason、
更改 #define CHANNEL B_AS_ZRO_PRD_REF 后、我可以在 EPWM1B 上看到高分辨率 0。
但是、我已经浏览过我的代码、发现这个宏仅用于更新 CMPB 寄存器值、但是我没有在操作鉴定配置中使用 CMPB、您能不能帮助我知道为什么 CMPB 必须以高分辨率更新?
以下是使用 CHANNEL B_AS_ZRO_PRD_REF 的唯一情况。
HRPWM_setCounterCompareValue (EPWM1_base、HRPWM_COUNTER_COMPARE_A、compCount);
#IF CHANNEL B_AS_ZRO_PRD_REF = 0
HRPWM_setCounterCompareValue (EPWM1_base、HRPWM_COUNTER_COMPARE_B、compCount);
#endif