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.

CCS/TMS320F28379D: Configure PWM generator for 3-phase inverter application

Part Number: TMS320F28379D

Tool/software: Code Composer Studio

Dear all,

I'm trying to configure the TMS320F28379D PWM generator, but I can't get the desired behavior. Let me describe how I configured a PWM channel:

1. PWM channel is configured to operate at 20 kHz (50 us) frequency in up-down-count mode.

2. PWM channel needs to work in a complementary mode, i.e. B output is inverted A output. A and B are outputs of a PWM channel.

3. Dead-time needs to be inserted on the rising edge for both PWM channels, and it should not be inserted on the falling edge. I'm not sure if I did this properly. According to Figure 14-33. Configuration Options for the Dead-Band Submodule, pp. 1717/2668, in Technical Reference Manual - SPRUHM8G, it seems that this can be achieved in four ways:

(3-1) OutA = PWMxA, OutB = PWMxA***, where PWMxA*** is delayed (both falling and rising edge) and inverted PWMxA signal
(3-2) OutA = PWMxB***, OutB = PWMxB, where PWMxB*** is delayed (both falling and rising edge) and inverted PWMxB signal
(3-3) OutA = PWMxA*, OutB = PWMxA**, where PWMxA* is delayed (rising edge) PWMxA, and PWMxA** is delayed (falling edge) and inverted PWMxA signal
(3-4) OutA = PWMxB**, OutB = PWMxB*, where PWMxB* is delayed (rising edge) PWMxB, and PWMxB** is delayed (falling edge) and inverted PWMxB signal

There are few other similar possibilities due to the OUTSWAP bits, but the problem remains the same. What is the problem? Well the problem is that in all dead-band modes only one signal, PWMxA or PWMxB, is used as a source to generate both outputs. You will see why is this a problem in bullet 4.

4. I want to be able to manually disconnect PWM channels from the output, but the PWM channel should still be running, because I use PWM as a source for ADC trigger and some other stuff. Now there is AQCSFRC register with CSFB and CSFA bits to force PWMxA and PWMxB to a certain state, without having to stop the PWM module clock. However, this register comes before the dead-band submodule, which means that it affects PWMxA and PWMxB on the input of the dead-band submodule. If you consider for example that OutA = PWMxA and OutB = PWMxA***, it is obvious that CSFB does not affect OutB, which means that if I force a high or low state on OutA = PWMxA using CSFA, the OutB will be in the opposite state of OutA.

Question is: How should I approach this? Is there any other way to configure dead-band generator to get the dead-time insertion, and to be able to use AQCSFRC to force both PWMxA and PWMxB to low state when needed? Or if this is not an option, what should I use to "disconnect PWM from GPIO"? Should I reconfigure GPIO directly (I don't like this approach)?

Here is my function used to configure a PWM channel.

void Inverter_InitEPwm(volatile struct EPWM_REGS *EPwmRegs)
{
    // The ePWM time base clock is determined by the following
    // parameters: EPWMCLK, CLKDIV, and HSPCLKDIV
    // EPWMCLK = PLLCLK/EPWMCLKDIV (200 MHz)
    // TBCLK = EPWMCLK/(HSPCLKDIV*CLKDIV) (200 MHz)

    // Action qualifier continuous S/W force register
    //EPwmRegs->AQCSFRC.bit.CSFB = 0b01;  // Forces a continuous low on output B
    //EPwmRegs->AQCSFRC.bit.CSFA = 0b01;  // Forces a continuous low on output A

    // Time base control register (1)
    //EPwmRegs->TBCTL.bit.FREE_SOFT = 0b11;   // Free run (#update)
    EPwmRegs->TBCTL.bit.PHSDIR = 0b1;       // Count up after a synchronization event
    EPwmRegs->TBCTL.bit.CLKDIV = 0b000;     // Time base clock prescale: /1
    EPwmRegs->TBCTL.bit.HSPCLKDIV = 0b000;  // High speed time base clock prescale: /1
    EPwmRegs->TBCTL.bit.SYNCOSEL = 0b01;    // Sync output select: TBCTR=0x00
    EPwmRegs->TBCTL.bit.PRDLD = 0b0;        // The TBPRD is loaded from its shadow register when TBCTR=0x00
    EPwmRegs->TBCTL.bit.PHSEN = 0b0;        // Do not load the TBCTR from TBPHS
    EPwmRegs->TBCTL.bit.CTRMODE = 0b10;     // Counter mode: up-down-count mode

    // Time base control register (2)
    EPwmRegs->TBCTL2.bit.PRDLDSYNC = 0b00;  // Shadow to active load of TBPRD occurs only when TBCTR=0x00

    // Counter compare control register (1)
    EPwmRegs->CMPCTL.bit.LOADBSYNC = 0b00;  // Shadow to active CMPB:CMPBHR occurs according to LOADBMODE bits
    EPwmRegs->CMPCTL.bit.LOADASYNC = 0b00;  // Shadow to active CMPA:CMPAHR occurs according to LOADAMODE bits
    EPwmRegs->CMPCTL.bit.SHDWBMODE = 0b0;   // Shadow mode is used for CMPB:CMPBHR registers
    EPwmRegs->CMPCTL.bit.SHDWAMODE = 0b0;   // Shadow mode is used for CMPA:CMPAHR registers
    EPwmRegs->CMPCTL.bit.LOADBMODE = 0b00;  // Load CMPB:CMPBHR on TBCTR=0x00
    EPwmRegs->CMPCTL.bit.LOADAMODE = 0b00;  // Load CMPA:CMPAHR on TBCTR=0x00

    // Dead-band generator control register (1)
    EPwmRegs->DBCTL.bit.HALFCYCLE = 0b0;    // The dead-band counters are clocked at the TBCLK rate
    EPwmRegs->DBCTL.bit.DEDB_MODE = 0b0;    // not used
    EPwmRegs->DBCTL.bit.OUTSWAP = 0b00;     // PathA->OutA, PathB->OutB
    EPwmRegs->DBCTL.bit.SHDWDBFEDMODE = 0b0;    // Shadow register is not used for DBFED register
    EPwmRegs->DBCTL.bit.SHDWDBREDMODE = 0b0;    // Shadow register is not used for DBRED register
    EPwmRegs->DBCTL.bit.IN_MODE = 0b00;     // EPWMxA is source for falling- and rising-edge delay
    EPwmRegs->DBCTL.bit.POLSEL = 0b10;      // EPWMxB is inverted EPWMxA
    EPwmRegs->DBCTL.bit.OUT_MODE = 0b11;    // DBM is fully enabled (both RED and FED)

    // Action qualifier control register for output A
    EPwmRegs->AQCTLA.bit.CAD = 0b10;    // Force ePWMxA to high (down-count)
    EPwmRegs->AQCTLA.bit.CAU = 0b01;    // Force ePWMxA to low (up-count)

    // Dead-band generator rising edge delay
    // In up-down-count mode:
    //  Tdly = (DBRED+DBFED)/(2*TBCTR)*TBCLK (2.5 us)
    EPwmRegs->DBRED.bit.DBRED = 250;
    EPwmRegs->DBFED.bit.DBFED = 250;

    // Time base counter register
    EPwmRegs->TBCTR = 0x0000;               // Clear counter

    // Time base period register
    // Up-count or down-count mode: TPWM = (TBCPRD+1)*TBCLK
    // Up-down-count mode: TPWM = (2*TBCTR)*TBCLK
    EPwmRegs->TBPRD = 5000;                 // PWM period (50 us)

    // Counter compare A register
    EPwmRegs->CMPA.bit.CMPA = 0;            // Duty-cycle of ePWMxA output
}
  • I managed to solve the problem.

    1. The PWMxA and PWMxB outputs from Action Qualifier submodule are defined to be equal:

    EPwmRegs->AQCTLA.bit.CAD = 0b10;    // Force ePWMxA to high (down-count)
    EPwmRegs->AQCTLA.bit.CAU = 0b01;    // Force ePWMxA to low (up-count)
    EPwmRegs->AQCTLB.bit.CAD = 0b10;    // Force ePWMxB to high (down-count)
    EPwmRegs->AQCTLB.bit.CAU = 0b01;    // Force ePWMxB to low (up-count)

    2. The dead-band submodule is defined as follows:

    OutA = PWMxA*, where PWMxA* is delayed (rising edge) PWMxA signal.
    OutB = PWMxB**, where PWMxB** is delayed (falling edge) and inverted PWMxB signal.

    EPwmRegs->DBCTL.bit.DEDB_MODE = 0b0;
    EPwmRegs->DBCTL.bit.OUTSWAP = 0b00;
    EPwmRegs->DBCTL.bit.IN_MODE = 0b10;
    EPwmRegs->DBCTL.bit.POLSEL = 0b10;
    EPwmRegs->DBCTL.bit.OUT_MODE = 0b11;

    3. To disconnect PWM from the output, write to the following bits in EPwmRegs:

    AQSFRC.bit.CSFB = 0b10; // Forces a continuous high on PWMxB, which means that OutB will be low
    AQSFRC.bit.CSFA = 0b01; // Forces a continuous low on PWMxA, which means that OutA will be low

  • Hi Marko,

    Thanks for posting the resolution to your issue.