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.

TMS320F280039C: Problems with dead band of the HRPWM

Part Number: TMS320F280039C
Other Parts Discussed in Thread: LAUNCHXL-F280039C, , C2000WARE, SYSCONFIG

Hello TI-experts,

I would like to generate symmetrical pwm signals with high resolution, complementary outputs and dead times. I am using the TMS320F280039C on the LAUNCHXL-F280039C.

Without hr-mode my ePWM module seems to work correctly with the required dead time. HR mode without complementarty output signals are working fine too.


I have already checked my configuration of the hr mode by creating an auxiliary output (ePWMxB) which is set if the timer is zero and which is cleared when the counter reachs the period. By doing this I was able to chek the center alignment. Looks fine so far.


But when I try to combine both, the delay of the dead band module are not as expected. The blanking times are unequal.

I have created a test case which shows the problem. This is how I configure the ePWM modules:

void init_pwm(void)
{

    // Disables TBCLKSYNC for correct synchronisation of multiple ePWM modules
    EALLOW;
    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0;
    EDIS;

    uint16_t i;
    for(i = 1; i < 4; i++)
    {
        // Time-Base Submodule
        (*ePWM[i]).TBPRD = 600;         // Set timer period
        (*ePWM[i]).TBPRDHR = 0;                 // HR Period

        (*ePWM[i]).TBCTR = 0x0000;              // Clear counter

        (*ePWM[i]).TBCTL.bit.PRDLD = 0;         // Active Period Reg Load from Shadow
        (*ePWM[i]).TBCTL.bit.CTRMODE = 2;       // Up-Down-Count mode
        (*ePWM[i]).TBCTL.bit.FREE_SOFT = 2;     // free run in emulation mode
        (*ePWM[i]).TBCTL.bit.PHSDIR = 1;        // Count up after the synchronization event
        (*ePWM[i]).TBCTL.bit.PHSEN = 0;         // Disable load event when an EPWMxSYNCI input signal occurs
        (*ePWM[i]).TBCTL.bit.HSPCLKDIV = 0;     // Clock ratio / 1
        (*ePWM[i]).TBCTL.bit.CLKDIV = 0;        // Clock ratio / 1

        // Synchronization in- and output
        (*ePWM[i]).EPWMSYNCINSEL.bit.SEL = 0;    // Disables all inputs for this module
        (*ePWM[i]).EPWMSYNCOUTEN.bit.SWEN = 0;   // Disable EPWMxSYNCO at SWFSYNC

        // Counter-Compare Submodule
        (*ePWM[i]).CMPCTL.bit.LOADAMODE = 0;     // Load CMPA when TBCTR = 0
        (*ePWM[i]).CMPCTL.bit.SHDWAMODE = 0;     // enable CMPA shadow mode
        (*ePWM[i]).CMPA.bit.CMPA = 20;  // Set default CMPA value

        // Action-Qualifier Submodule
        // ePWMxA on-time = 2* CMPA  * (1 / 120 MHz)
        // ePWMxB on-time = (1200 - 2 * CMPA) * (1 / 120 MHz)
        (*ePWM[i]).AQCTLA.bit.ZRO = 2;           // Set ePWMxA when TBCTR = 0
        (*ePWM[i]).AQCTLA.bit.CAU = 1;           // Clear ePWMxA when TBCTR = CMPA on up-count
        (*ePWM[i]).AQCTLA.bit.CAD = 2;           // Set ePWMxA when TBCTR = CMPA on down-count

        // ePWMxA on-time = (1200 - 2 * CMPA) * (1 / 120 MHz)
        // ePWMxB on-time = 2* CMPA  * (1 / 120 MHz)
        //(*ePWM[i]).AQCTLA.bit.ZRO = 1;           // Clear ePWMxA when TBCTR = 0
        //(*ePWM[i]).AQCTLA.bit.CAU = 2;           // Set ePWMxA when TBCTR = CMPA on up-count
        //(*ePWM[i]).AQCTLA.bit.CAD = 1;           // Clear ePWMxA when TBCTR = CMPA on down-count


        (*ePWM[i]).DBCTL.bit.HALFCYCLE = 1;     // clock DB counters at half TBCLK rate
        (*ePWM[i]).DBCTL.bit.DEDB_MODE = 0;         // RED to Input A, FED to Input A
        (*ePWM[i]).DBCTL.bit.IN_MODE = 0;
        (*ePWM[i]).DBCTL.bit.OUT_MODE = 3;          // RED to A path, FED to B path
        (*ePWM[i]).DBCTL.bit.POLSEL = 2;            // B path inverted
        (*ePWM[i]).DBCTL.bit.OUTSWAP = 0;           // A path to OutA, B path to OutB
        (*ePWM[i]).DBCTL.bit.SHDWDBFEDMODE = 1;     // FED shandow load mode
        (*ePWM[i]).DBCTL.bit.SHDWDBREDMODE = 1;     // RED shandow load mode
        (*ePWM[i]).DBCTL.bit.LOADFEDMODE = 2;       // Load on TBCTR = 0 or TBCTR = PRD
        (*ePWM[i]).DBCTL.bit.LOADREDMODE = 2;       // Load on TBCTR = 0 or TBCTR = PRD

        (*ePWM[i]).DBRED.bit.DBRED = 10;
        (*ePWM[i]).DBFED.bit.DBFED = 10;

        // Digital-Compare Submodule
        EALLOW;
        (*ePWM[i]).DCTRIPSEL.bit.DCAHCOMPSEL = 3;    // select TRIP4 as Digital Compare A High Input
        (*ePWM[i]).DCACTL.bit.EVT1FRCSYNCSEL = 1;    // DCAEVT1 Force Source is passed through asynchronously
        EDIS;

        // Trip-Zone Submodule
        EALLOW;
        (*ePWM[i]).TZSEL.bit.DCAEVT1 = 1;          // Enable DCAEVT1 as a one-shot trip source
        (*ePWM[i]).TZDCSEL.bit.DCAEVT1 = 2;        // Digital Compare Output A Event 1 Selection: DCAH = high, DCAL = don't care
        (*ePWM[i]).TZCTL.bit.TZA = 2;              // Force EPWMxA to a low state on trip event
        (*ePWM[i]).TZCTL.bit.TZB = 2;              // Force EPWMxB to a low state on trip event
        EDIS;

        if(i == 1)
        {
            // Trip-Zone Submodule
            EALLOW;
            (*ePWM[i]).TZEINT.bit.OST = 1;           // Enable Trip-zone One-Shot Interrupt
            EDIS;
            // Event-Trigger Submodule
            (*ePWM[i]).ETSEL.bit.INTSEL = 0;         // Disables Interrupt when TBCTR = 0
            (*ePWM[i]).ETSEL.bit.INTEN = 1;          // Enable INT
            (*ePWM[i]).ETSEL.bit.SOCAEN = 1;         // Enable EPWMxSOCA pulse
            (*ePWM[i]).ETSEL.bit.SOCASEL = 1;        // Enable EPWMxSOCA  event time-base counter equal to zero
            (*ePWM[i]).ETPS.bit.INTPRD = 1;          // Interrupt on first event
            (*ePWM[i]).ETPS.bit.SOCAPRD = 1;         // EPWMxSOCA on first event
        }
        else
        {
            // Event-Trigger Submodule
            (*ePWM[i]).ETSEL.bit.INTSEL = 0;         // Disables Interrupt when TBCTR = 0
            (*ePWM[i]).ETSEL.bit.INTEN = 0;          // Disable INT
            (*ePWM[i]).ETPS.bit.INTPRD = 0;          // Disable the interrupt event counter
        }


        EALLOW;
        (*ePWM[i]).HRCNFG.all = 0x0;
        (*ePWM[i]).HRCNFG.bit.EDGMODE = 3;          // MEP control of both edges
        (*ePWM[i]).HRCNFG.bit.CTLMODE = 0;          // Duty control mode
        (*ePWM[i]).HRCNFG.bit.HRLOAD = 2;           // Load CMPAHR when TBCTR = 0 or TBCTR = PRD
        (*ePWM[i]).HRCNFG.bit.AUTOCONV = 1;         // Automatic HRMSTEP scaling is enabled

        (*ePWM[i]).HRCNFG2.bit.EDGMODEDB = 3;       // MEP control of both edges (DBREDHR and DBFEDHR)
        (*ePWM[i]).HRCNFG2.bit.CTLMODEDBRED = 2;    // load shadow register when CTR = Zero or CTR = PRD
        (*ePWM[i]).HRCNFG2.bit.CTLMODEDBFED = 2;    // load shadow register when CTR = Zero or CTR = PRD

        (*ePWM[i]).HRPWR.bit.CALPWRON = 1;          // Enables MEP calibration logic

        (*ePWM[i]).HRPCTL.bit.HRPE = 1;             // High resolution period enabled
        (*ePWM[i]).HRPCTL.bit.TBPHSHRLOADE = 1;     // Synchronize the high-resolution phase on a TBCTL[SWFSYNC] event
        EDIS;

        (*ePWM[i]).TBCTL.bit.PHSEN = 1;             // load TBPHS from shadow on a TBCTL[SWFSYNC] event
        (*ePWM[i]).TBCTL.bit.SWFSYNC = 1;           // generates a TBCTL[SWFSYNC] event

    }


    EALLOW;
    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;       // Enable EPWM Time Base Clock gating
    EDIS;


    while(SFO() == 0)
    {
        // Wait until SFO has finished
    }
}

Measurement :



Measurement data:
Channel 1: ePWM[1]: Output A
Channel 2: ePWM[1]: Output B
Channel 3: ePWM[2]: Output A
Channel 4: ePWM[2]: Output B

Epwm clock frequency = 120 MHz
TBPRD = 600
up-down-count mode
RED of ePWM[1] = 10
FED of ePWM[1] = 10
CMPA of ePWM[1] = 20
CMPAHR of ePWM[1] = 32768

RED of ePWM[2] = 10
FED of ePWM[2] = 10
CMPA of ePWM[1] = 20
CMPAHR of ePWM[1] = 0

The alignment of Channel 1 and Channel 3 are as expected. Because I use the up-down-count mode the on-time of Channel 1 is one clock cycle (1 / 120 MHz = 8,33 ns) longer as the on time of channel 3, aligned to the center of both on-times. Channel 3 and Channel 4 are also fine. But the blanking times of ePWM[1] are wrong. As you can see on the cursors time measurement, the difference between the complemntary oututs of the two ePWM modules are one clock cycle, instead of an half clock cycle.

How can I achieve proper behavior of the dead band submodule in hr-mode with complementary output signals?

Thank you in advance.

Reagrds
Stefan

  • Hi,

    I was looking for some example projects or reference designs using symmetrical HRPWM (up-down-count mode) in a configuration with FED and RED in complementary output mode (AHC), but I haven't found anything yet.

    Do you have an example of this configuration?

    Either in Bitfield or with the Driverlib would be helpful for me. Maybe there is also an example for another controller?

    Is the Type 4 ePWM / HRPWM module at all suitable for this kind of operation?

    Best regards, Stefan

  • Hello Stefan,

    HRPWM_ex4_duty_updown_sfo utilizes both rising & falling edge control in up-down-count mode, an example that exists in C2000Ware for the F280039C! If you continue to have concerns, I would ask that you provide the ns MEP step size, please- this will allow me to understand the waveforms much more clearly.

    Regards,

    Jason Osborn

  • Hi Jason,

    Thank you very much. I already know the HRPWM_ex4_duty_updown_sfo example. It uses the hrpwm, but not the dead-time submodule.

    There are 52 msteps per pwm clock cycles. Therefore one mstep is about 160 ns. Because of autoconversion the CMPAHR value of 32768 (2^15, or 26 mstep) leads to 4,167 ns of high resolution time, which you can see on the waveforms by comparing Channel 1 with Channel 3. CMPAHR of Channel 3 is equal to zero.

    The problem is that the falling edge of Channel 2, which is the complementary ePWM output of channel 1, is 8,333 ns before the falling edge of Channel 4, which is the complementary output of the second ePWM module with CMPAHR cleared respectaly. Both rising edges of the complementary signals are synchronous. So the on-times of the ePWM modules are not center aligned.

    In this configuration I expect just 4.167 ns difference between both transition, which yields to centred aligned waveforms.

    This is the reason I trink something is wrong in my configuration.

    Best regards,

    Stefan

  • Stefan,

    Apologies, but I'm not sure I understand. The mentioned example does utilize the deadband (DB) submodule. Would you please send a screenshot of the HRPWM control registers & the DB control registers in CCS? This will help greatly in tracking down exactly what's going on, I think.

    Additionally, I'm uncertain what you meant when you said that because you're using up-down count, there's a 1 TBCLK delay between the two ePWM modules. What about operating in this mode are you saying is causing a delay?

    Regards,

    Jason Osborn

  • Hi Jason,

    I'm sorry, but there is surely no use of the Dead-Band submodule in HRPWM_ex4_duty_updown_sfo. At least within C2000 Ware 4.02.00.00:

    Here you can see that no Dead-Band associated register is configured in the board.c file:

    The sysconfig is configured without the Dead-Band submodule too:

    Are you maybe using another example with an identical name?

    "Additionally, I'm uncertain what you meant when you said that because you're using up-down count, there's a 1 TBCLK delay between the two ePWM modules. What about operating in this mode are you saying is causing a delay?"

    I wrote in my first message that the delay of the dead zone module is not as expected. This meant the RED and FED times of the Dead-Band Generator submodule. In up-down-count mode with HRPWM and center-aligned pulses, a CMPAHR value of 2^15 causes an increase of the pulse by a total of one time-base clock cycle, compared to a CMPAHR value of zero. This is what I wanted to describe.Sorry for the confusion.

    Back to my question or rather problem:

    I want to generate the ePWMxA and ePWMxB outputs in active-high complementary mode (AHC), as described on Page 2195 of the TRM (SPRUIW9A). I have created a drawing (TBPRD = 6, RED = FED = 1) that shows the desired output behavior of my ePWM modules:

    This works fine, but only without the HR-mode turend on. I expect the following behavior in the HR mode:

    Please note that the action-qualifier conditions are not the same as in my first post. There are inverted. This is the code of the action-qualifier configuration shown in the figure above with the high resolution mode turned on:

    //#############################################################################
    //
    // FILE:   adc_ex1_soc_epwm.c
    //
    // TITLE:  ADC ePWM Triggering
    //
    //! \addtogroup bitfield_example_list
    //! <h1>ADC ePWM Triggering</h1>
    //!
    //! This example sets up ePWM1 to periodically trigger a conversion on ADCA.
    //!
    //! \b External \b Connections \n
    //!  - A1 should be connected to a signal to convert
    //!
    //! \b Watch \b Variables \n
    //! - \b adcAResults - A sequence of analog-to-digital conversion samples from
    //!   pin A1. The time between samples is determined based on the period
    //!   of the ePWM timer.
    //!
    //
    //#############################################################################
    //
    //
    // $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 "f28x_project.h"
    #include "sfo_v8.h"
    
    void init_pwm_gpio(void);
    void init_pwm(void);
    
    volatile struct EPWM_REGS *ePWM[3] = {0, &EPwm1Regs, &EPwm2Regs};
    
    Uint16 status = SFO_INCOMPLETE;
    int MEP_ScaleFactor = 0; //scale factor value
    
    //
    // Main
    //
    void main(void)
    {
        //
        // Initialize device clock and peripherals
        //
        InitSysCtrl();
    
        //
        // Initialize GPIO
        //
        InitGpio();
    
        //
        // Disable CPU interrupts
        //
        DINT;
    
        //
        // Initialize the PIE control registers to their default state.
        // The default state is all PIE interrupts disabled and flags
        // are cleared.
        //
        InitPieCtrl();
    
        //
        // Disable CPU interrupts and clear all CPU interrupt flags:
        //
        IER = 0x0000;
        IFR = 0x0000;
    
        //
        // Initialize the PIE vector table with pointers to the shell Interrupt
        // Service Routines (ISR).
        //
        InitPieVectTable();
    
        init_pwm_gpio();
        init_pwm();
    
        EINT;           // Enable Global interrupt INTM
        ERTM;           // Enable Global realtime interrupt DBGM
    
    
        while(1)
        {
    
        }
    }
    
    void init_pwm_gpio(void)
    {
        EALLOW;
        GpioCtrlRegs.GPAPUD.bit.GPIO0 = 1;      // Disable pull-up on GPIO0 (EPWM1A)
        GpioCtrlRegs.GPAPUD.bit.GPIO1 = 1;      // Disable pull-up on GPIO1 (EPWM1B)
    
        GpioCtrlRegs.GPAPUD.bit.GPIO2 = 1;      // Disable pull-up on GPIO2 (EPWM2A)
        GpioCtrlRegs.GPAPUD.bit.GPIO3 = 1;      // Disable pull-up on GPIO3 (EPWM2B)
    
        GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1;     // Configure GPIO0 as EPWM1A
        GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1;     // Configure GPIO1 as EPWM1B
    
        GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 1;     // Configure GPIO2 as EPWM2A
        GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 1;     // Configure GPIO3 as EPWM2B
    
        GpioCtrlRegs.GPALOCK.bit.GPIO0 = 1;     // lock GPIO0 configuration
        GpioCtrlRegs.GPALOCK.bit.GPIO1 = 1;     // lock GPIO1 configuration
    
        GpioCtrlRegs.GPALOCK.bit.GPIO2 = 1;     // lock GPIO2 configuration
        GpioCtrlRegs.GPALOCK.bit.GPIO3 = 1;     // lock GPIO3 configuration
    
        EDIS;
    }
    
    void init_pwm(void)
    {
    
        // Disables TBCLKSYNC for correct synchronisation of multiple ePWM modules
        EALLOW;
        CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0;
        EDIS;
    
        uint16_t i;
        for(i = 1; i < 3; i++)
        {
            // Time-Base Submodule
            (*ePWM[i]).TBPRD = 600;                 // Set timer period
            (*ePWM[i]).TBPRDHR = 0;                 // HR Period
    
            (*ePWM[i]).TBCTR = 0x0000;              // Clear counter
    
            (*ePWM[i]).TBCTL.bit.PRDLD = 0;         // Active Period Reg Load from Shadow
            (*ePWM[i]).TBCTL.bit.CTRMODE = 2;       // Up-Down-Count mode
            (*ePWM[i]).TBCTL.bit.FREE_SOFT = 2;     // free run in emulation mode
            (*ePWM[i]).TBCTL.bit.PHSDIR = 1;        // Count up after the synchronization event
            (*ePWM[i]).TBCTL.bit.PHSEN = 0;         // Disable load event when an EPWMxSYNCI input signal occurs
            (*ePWM[i]).TBCTL.bit.HSPCLKDIV = 0;     // Clock ratio / 1
            (*ePWM[i]).TBCTL.bit.CLKDIV = 0;        // Clock ratio / 1
    
            // Synchronization in- and output
            (*ePWM[i]).EPWMSYNCINSEL.bit.SEL = 0;    // Disables all inputs for this module
            (*ePWM[i]).EPWMSYNCOUTEN.bit.SWEN = 0;   // Disable EPWMxSYNCO at SWFSYNC
    
            // Counter-Compare Submodule
            (*ePWM[i]).CMPCTL.bit.LOADAMODE = 0;     // Load CMPA when TBCTR = 0
            (*ePWM[i]).CMPCTL.bit.SHDWAMODE = 0;     // enable CMPA shadow mode
            (*ePWM[i]).CMPA.bit.CMPA = 20;           // Set default CMPA value
    
            // Action-Qualifier Submodule
            // ePWMxA on-time = (1200 - 2 * CMPA) * (1 / 120 MHz)
            // ePWMxB on-time = 2* CMPA  * (1 / 120 MHz)
            (*ePWM[i]).AQCTLA.bit.ZRO = 1;           // Clear ePWMxA when TBCTR = 0
            (*ePWM[i]).AQCTLA.bit.CAU = 2;           // Set ePWMxA when TBCTR = CMPA on up-count
            (*ePWM[i]).AQCTLA.bit.CAD = 1;           // Clear ePWMxA when TBCTR = CMPA on down-count
    
    
            (*ePWM[i]).DBCTL.bit.HALFCYCLE = 1;         // clock DB counters at half TBCLK rate
            (*ePWM[i]).DBCTL.bit.DEDB_MODE = 0;         // RED to Input A, FED to Input A
            (*ePWM[i]).DBCTL.bit.IN_MODE = 0;
            (*ePWM[i]).DBCTL.bit.OUT_MODE = 3;          // RED to A path, FED to B path
            (*ePWM[i]).DBCTL.bit.POLSEL = 2;            // B path inverted
            (*ePWM[i]).DBCTL.bit.OUTSWAP = 0;           // A path to OutA, B path to OutB
            (*ePWM[i]).DBCTL.bit.SHDWDBFEDMODE = 1;     // FED shandow load mode
            (*ePWM[i]).DBCTL.bit.SHDWDBREDMODE = 1;     // RED shandow load mode
            (*ePWM[i]).DBCTL.bit.LOADFEDMODE = 2;       // Load on TBCTR = 0 or TBCTR = PRD
            (*ePWM[i]).DBCTL.bit.LOADREDMODE = 2;       // Load on TBCTR = 0 or TBCTR = PRD
    
            (*ePWM[i]).DBRED.bit.DBRED = 10;
            (*ePWM[i]).DBFED.bit.DBFED = 10;
    
            EALLOW;
            (*ePWM[i]).HRCNFG.all = 0x0;
            (*ePWM[i]).HRCNFG.bit.EDGMODE = 3;          // MEP control of both edges
            (*ePWM[i]).HRCNFG.bit.CTLMODE = 0;          // Duty control mode
            (*ePWM[i]).HRCNFG.bit.HRLOAD = 2;           // Load CMPAHR when TBCTR = 0 or TBCTR = PRD
            (*ePWM[i]).HRCNFG.bit.AUTOCONV = 1;         // Automatic HRMSTEP scaling is enabled
    
            (*ePWM[i]).HRCNFG2.bit.EDGMODEDB = 3;       // MEP control of both edges (DBREDHR and DBFEDHR)
            (*ePWM[i]).HRCNFG2.bit.CTLMODEDBRED = 2;    // load shadow register when CTR = Zero or CTR = PRD
            (*ePWM[i]).HRCNFG2.bit.CTLMODEDBFED = 2;    // load shadow register when CTR = Zero or CTR = PRD
    
            (*ePWM[i]).HRPWR.bit.CALPWRON = 1;          // Enables MEP calibration logic
    
            (*ePWM[i]).HRPCTL.bit.HRPE = 1;             // High resolution period enabled
            (*ePWM[i]).HRPCTL.bit.TBPHSHRLOADE = 1;     // Synchronize the high-resolution phase on a TBCTL[SWFSYNC] event
            EDIS;
    
            (*ePWM[i]).TBCTL.bit.PHSEN = 1;             // load TBPHS from shadow on a TBCTL[SWFSYNC] event
            (*ePWM[i]).TBCTL.bit.SWFSYNC = 1;           // generates a TBCTL[SWFSYNC] event
    
        }
    
        EALLOW;
        CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;       // Enable EPWM Time Base Clock gating
        EDIS;
    
        while(SFO() == 0)
        {
            // Wait until SFO has finished
        }
    }
    

    You can run in on the LAUNCHXL-F280039C.

    The inversion on action-qualifiers events doesen't matter, because the results are the same in high resolution mode: I get the same behavior which I tried to describe in my last post. The "on-times", where ePWM1A and ePWM2A are both high, are symmetrical. Center point is the half on-time of the both outputs. This is showen by the "true center point" in my drawings. Because of the RED and FED of the Dead-Band Submodule, this point is not when TBCTRL = PRD. The RED and FED times behave differently than expected, if the CMPAHR register is not equal to zero. Although RED and FED have the same value, the times are different. If I want to operate several ePWM modules synchronously, this leads to the fact that the on-times of the ePWMxB outputs are not centered.

    Here is a measurement of the code from the listing:

    Channel 1: ePWM1A

    Channel 2: ePWM1B

    Channel 3: ePWM2A

    Channel 4: ePWM2B

    The parameters of the measurement are shown in the following screenshot:

    The Time-Base clock frequency is still 120 MHz. Again, the RED and FED times of the module Dead-Band Generator submodule are different, as can be seen in the measurement. The RED time between Channel 1 and Channel 2 (both ePWM1) is one half Time-Base clock period too long. And the FED time between the mentioned Channels is one half Time-Base clock period too short.

    Do you expect this behavior? Or should both complementary outputs be symmetrical, as drawn in my picture above?

    Best regards,

    Stefan

  • Hello Stefan,

    Ah, apologies about the example! I had made some changes to the submodule to better assist another e2e user some time ago and had forgotten about the changes entirely until just now. Beyond that, I'll be doing some testing on my end. I think I have some idea of what's happening, and I want to confirm it. I'll get back to you by the end of day tomorrow at the latest.

    Apologies again for my prior confusion,

    Jason Osborn

  • Stefan,

    Would you kindly add the following lines to your initialization:

            (*ePWM[i]).HRCNFG.bit.CTLMODEB = 0;          // Duty control mode
            (*ePWM[i]).HRCNFG.bit.HRLOADB = 2;           // Load CMPAHR when TBCTR = 0 or TBCTR = PRD

    And (after also loading the same value into CMPBHR as you did into CMPAHR) let me know if you're getting the expected output? CMPBHR is utilized to control HRPWM behavior, not to adjust AQ behavior.

    Regards,

    Jason Osborn

    (As well, you mention DEDBHR control specifically- At the moment, you have no inputs into the DBREDHR and DBFEDHR registers, which are how that particular functionality is controlled.)

  • Hi Jason,

    Thank you very much. With your two lines of code and writing both CMPAHR and CMPBHR registers with the same value I get these waveforms:

    Channel 1: ePWM1A

    Channel 2: ePWM1B

    Channel 3: ePWM2A

    Channel 4: ePWM2B

    Parameters of the obove measurement:

    Because CTLMODEB and HRLOADB specify the behavior or action taken with the CMPBHR values, I tried to set also the EDGMODEB bit in the HRCNFG register to 0x3 (MEP control of both edges). The complete ePWM configuration code is as shown below:

    void init_pwm(void)
    {
    
        // Disables TBCLKSYNC for correct synchronisation of multiple ePWM modules
        EALLOW;
        CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0;
        EDIS;
    
        uint16_t i;
        for(i = 1; i < 3; i++)
        {
            // Time-Base Submodule
            (*ePWM[i]).TBPRD = 600;                 // Set timer period
            (*ePWM[i]).TBPRDHR = 0;                 // HR Period
    
            (*ePWM[i]).TBCTR = 0x0000;              // Clear counter
    
            (*ePWM[i]).TBCTL.bit.PRDLD = 0;         // Active Period Reg Load from Shadow
            (*ePWM[i]).TBCTL.bit.CTRMODE = 2;       // Up-Down-Count mode
            (*ePWM[i]).TBCTL.bit.FREE_SOFT = 2;     // free run in emulation mode
            (*ePWM[i]).TBCTL.bit.PHSDIR = 1;        // Count up after the synchronization event
            (*ePWM[i]).TBCTL.bit.PHSEN = 0;         // Disable load event when an EPWMxSYNCI input signal occurs
            (*ePWM[i]).TBCTL.bit.HSPCLKDIV = 0;     // Clock ratio / 1
            (*ePWM[i]).TBCTL.bit.CLKDIV = 0;        // Clock ratio / 1
    
            // Synchronization in- and output
            (*ePWM[i]).EPWMSYNCINSEL.bit.SEL = 0;    // Disables all inputs for this module
            (*ePWM[i]).EPWMSYNCOUTEN.bit.SWEN = 0;   // Disable EPWMxSYNCO at SWFSYNC
    
            // Counter-Compare Submodule
            (*ePWM[i]).CMPCTL.bit.LOADAMODE = 0;     // Load CMPA when TBCTR = 0
            (*ePWM[i]).CMPCTL.bit.SHDWAMODE = 0;     // enable CMPA shadow mode
            (*ePWM[i]).CMPA.bit.CMPA = 20;           // Set default CMPA value
    
            // Action-Qualifier Submodule
            // ePWMxA on-time = (1200 - 2 * CMPA) * (1 / 120 MHz)
            // ePWMxB on-time = 2* CMPA  * (1 / 120 MHz)
            (*ePWM[i]).AQCTLA.bit.ZRO = 1;           // Clear ePWMxA when TBCTR = 0
            (*ePWM[i]).AQCTLA.bit.CAU = 2;           // Set ePWMxA when TBCTR = CMPA on up-count
            (*ePWM[i]).AQCTLA.bit.CAD = 1;           // Clear ePWMxA when TBCTR = CMPA on down-count
    
    
            (*ePWM[i]).DBCTL.bit.HALFCYCLE = 1;         // clock DB counters at half TBCLK rate
            (*ePWM[i]).DBCTL.bit.DEDB_MODE = 0;         // RED to Input A, FED to Input A
            (*ePWM[i]).DBCTL.bit.IN_MODE = 0;
            (*ePWM[i]).DBCTL.bit.OUT_MODE = 3;          // RED to A path, FED to B path
            (*ePWM[i]).DBCTL.bit.POLSEL = 2;            // B path inverted
            (*ePWM[i]).DBCTL.bit.OUTSWAP = 0;           // A path to OutA, B path to OutB
            (*ePWM[i]).DBCTL.bit.SHDWDBFEDMODE = 1;     // FED shandow load mode
            (*ePWM[i]).DBCTL.bit.SHDWDBREDMODE = 1;     // RED shandow load mode
            (*ePWM[i]).DBCTL.bit.LOADFEDMODE = 2;       // Load on TBCTR = 0 or TBCTR = PRD
            (*ePWM[i]).DBCTL.bit.LOADREDMODE = 2;       // Load on TBCTR = 0 or TBCTR = PRD
    
            (*ePWM[i]).DBRED.bit.DBRED = 10;
            (*ePWM[i]).DBFED.bit.DBFED = 10;
    
            EALLOW;
            (*ePWM[i]).HRCNFG.all = 0x0;
            (*ePWM[i]).HRCNFG.bit.EDGMODE = 3;          // MEP control of both edges
            (*ePWM[i]).HRCNFG.bit.CTLMODE = 0;          // Duty control mode
            (*ePWM[i]).HRCNFG.bit.HRLOAD = 2;           // Load CMPAHR when TBCTR = 0 or TBCTR = PRD
            (*ePWM[i]).HRCNFG.bit.AUTOCONV = 1;         // Automatic HRMSTEP scaling is enabled
    
            //
            // CMPBHR is used for duty-control with dead-band in up-down-count mode and must be set to same value as CMPA
            //
            (*ePWM[i]).HRCNFG.bit.EDGMODEB = 3;          // MEP control of both edges
            (*ePWM[i]).HRCNFG.bit.CTLMODEB = 0;          // Duty control mode
            (*ePWM[i]).HRCNFG.bit.HRLOADB = 2;           // Load CMPBHR when TBCTR = 0 or TBCTR = PRD
            //
    
            (*ePWM[i]).HRCNFG2.bit.EDGMODEDB = 3;       // MEP control of both edges (DBREDHR and DBFEDHR)
            (*ePWM[i]).HRCNFG2.bit.CTLMODEDBRED = 2;    // load shadow register when CTR = Zero or CTR = PRD
            (*ePWM[i]).HRCNFG2.bit.CTLMODEDBFED = 2;    // load shadow register when CTR = Zero or CTR = PRD
    
            (*ePWM[i]).HRPWR.bit.CALPWRON = 1;          // Enables MEP calibration logic
    
            (*ePWM[i]).HRPCTL.bit.HRPE = 1;             // High resolution period enabled
            (*ePWM[i]).HRPCTL.bit.TBPHSHRLOADE = 1;     // Synchronize the high-resolution phase on a TBCTL[SWFSYNC] event
            EDIS;
    
            (*ePWM[i]).TBCTL.bit.PHSEN = 1;             // load TBPHS from shadow on a TBCTL[SWFSYNC] event
            (*ePWM[i]).TBCTL.bit.SWFSYNC = 1;           // generates a TBCTL[SWFSYNC] event
    
        }
    
        EALLOW;
        CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;       // Enable EPWM Time Base Clock gating
        EDIS;
    
        while(SFO() == 0)
        {
            // Wait until SFO has finished
        }
    }

    Now it works as expected, see the following measurement and the corresponding parameters (Unchanged, with the exception of the EDGMODEB bits):

    Channel 1: ePWM1A

    Channel 2: ePWM1B

    Channel 3: ePWM2A

    Channel 4: ePWM2B

    Thank you very much for your help. I never thought that CMPBHR must also be used for this mode. I did not find anything in the TRM about this.

    Best regards,

    Stefan