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.

LaunchXL-F28377S PWM phase control

I am running 2 synchronous PWMs (4 outputs) to control an interleaved (2 phase) DC/DC converter.  I am trying to add 180° phase shift to one set of PWM outputs.

I have tried various values from 1 to 20000 in this line of code and it doesn't seem to have any affect.

EPwm6Regs.TBPHS.bit.TBPHS = 0x0000;            // Phase is 0

I also tried changing this line:


    EPwm6Regs.TBCTL.bit.PHSEN = TB_DISABLE;        // Disable phase loading

to this:


    EPwm6Regs.TBCTL.bit.PHSEN = TB_ENABLE;        // Disable phase loading

That killed my PWM and caused a constant output.

Is there something I am missing?

  • Hi,

    I've a very bad habit of spoon-feeding, let me do it one more time :)

    Here's the code for interleaving and all you've to do is modify your switching frequency and phase according to your application requirement.

     EALLOW;  
           SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;      // DISABLE TBCLK TILL EPWM CONFIGURATION IS COMPLETED
         EDIS; 
    
         EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up
         EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW;		
         EPwm1Regs.TBPRD = 600;   				   
         EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;    // Disable phase loading
         EPwm1Regs.TBPHS.half.TBPHS = 0x0000;       // Phase is 0
         EPwm1Regs.TBCTR = 0x0000;// Clear counter
         EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; // sync output pulse for pwm2 when ctr = 0;
         // Setup shadow register load on ZERO
         EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
         EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
         // Set Compare values
         EPwm1Regs.CMPA.half.CMPA = 0;    				// Set compare A value
         // Set actions
         EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET;            // Set PWM1A on Zero
         EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;          // Clear PWM1A on event A, up count
    
    
      //ePWM2 Configurations
         EPwm2Regs.TBPRD = 600; 						
         EPwm2Regs.TBCTL.bit.PHSEN = TB_ENABLE; 
         EPwm2Regs.TBPHS.half.TBPHS = 300;				// Set Phase register to TBPRD/2
         EPwm2Regs.TBCTR = 0;     
      
         EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; 	// Asymmetrical mode
         EPwm2Regs.TBCTL.bit.PRDLD = TB_SHADOW;
         EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN; 	// SYNC INPUT FROM EPWM1
         EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
         EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // load on CTR=Zero
         EPwm2Regs.AQCTLA.bit.ZRO = AQ_SET;            // Set PWM1A on Zero
         EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR;          // Clear PWM1A on event A, up count
         EPwm2Regs.CMPA.half.CMPA = 0;   				// Set compare B value
    
         EALLOW;  
             SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;      // ENABLE TBCLK TILL EPWM CONFIGURATION IS COMPLETED
         EDIS;

    Regards,

    Gautam

  • Thank you for the code. It gives these errors when I try to build:
    "../PWM_ADC-1.c", line 286: error #137: union "TBPHS_REG" has no field "half"
    "../PWM_ADC-1.c", line 293: error #137: union "CMPA_REG" has no field "half"
    "../PWM_ADC-1.c", line 310: error #137: union "TBPHS_REG" has no field "half"
    "../PWM_ADC-1.c", line 319: error #137: union "CMPA_REG" has no field "half"

    Errors are for these lines of code:
    EPwm1Regs.TBPHS.half.TBPHS = 0x0000; // Phase is 0
    EPwm1Regs.CMPA.half.CMPA = 0; // Set compare A value
    EPwm2Regs.TBPHS.half.TBPHS = 300; // Set Phase register to TBPRD/2
    EPwm2Regs.CMPA.half.CMPA = 0; // Set compare B value
  • I changed 'half' to 'bit' and that relinquished the errors but now I am at the same point I was before. PWM2 works fine but PWM6 gives constant output unless I change:

    EPwm6Regs.TBCTL.bit.PHSEN = TB_ENABLE;
    to:
    EPwm6Regs.TBCTL.bit.PHSEN = TB_DISABLE;
    After making that change, I get 4 PWM outputs, 2 sets of complimentary outputs with dead time and adjustable duty cycle but I still don't get the 180° phase difference that I need.

    Here's what I have for code:

    void InitEPwm2Example()
    {
    EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up
    EPwm2Regs.TBCTL.bit.PRDLD = TB_SHADOW;
    EPwm2Regs.TBPRD = PWM_PERIOD_SETTING; // Set timer period
    EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
    EPwm2Regs.TBPHS.bit.TBPHS = 0x0000; // Phase is 0
    EPwm2Regs.TBCTR = 0x0000;// Clear counter
    EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; // sync output pulse for pwm6 when ctr = 0;
    // Setup shadow register load on ZERO
    EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
    EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
    // Set Compare values
    EPwm2Regs.CMPA.bit.CMPA = 0; // Set compare A value
    // Set actions
    EPwm2Regs.AQCTLA.bit.ZRO = AQ_SET; // Set PWM1A on Zero
    EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Clear PWM1A on event A, up count

    // Setup compare
    EPwm2Regs.CMPA.bit.CMPA = PWM_PERIOD_SETTING * DUTY_CYCLE;

    // Active High complementary PWMs - setup the deadband
    EPwm2Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
    //EPwm2Regs.DBCTL.bit.POLSEL = DB_ACTV_LOC;
    EPwm2Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; ////////////////ACTIVE LOW/HIGH/////////////////////////////////////////////////
    EPwm2Regs.DBCTL.bit.IN_MODE = DBA_ALL;
    //Dead time - Prevents switch shoot-through
    EPwm2Regs.DBFED.bit.DBFED = DEAD_TIME_SETTING;
    EPwm2Regs.DBRED.bit.DBRED = DEAD_TIME_SETTING;
    EPwm2_DB_Direction = DB_UP;
    // Interrupt where we will modify the deadband
    EPwm2Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event
    EPwm2Regs.ETSEL.bit.INTEN = 1; // Enable INT
    EPwm2Regs.ETPS.bit.INTPRD = ET_3RD; // Generate INT on 3rd event
    }

    void InitEPwm6Example()
    {
    EPwm6Regs.TBPRD = PWM_PERIOD_SETTING;
    EPwm6Regs.TBCTL.bit.PHSEN = TB_ENABLE; //no PWM when this is enabled
    //EPwm6Regs.TBCTL.bit.PHSEN = TB_DISABLE;
    EPwm6Regs.TBPHS.bit.TBPHS = PWM_PERIOD_SETTING/2; // Set Phase register to TBPRD/2
    EPwm6Regs.TBCTR = 0;
    EPwm6Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Asymmetrical mode
    EPwm6Regs.TBCTL.bit.PRDLD = TB_SHADOW;
    EPwm6Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN; // SYNC INPUT FROM EPWM1
    EPwm6Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
    EPwm6Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // load on CTR=Zero
    EPwm6Regs.AQCTLA.bit.ZRO = AQ_SET; // Set PWM1A on Zero
    EPwm6Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Clear PWM1A on event A, up count
    EPwm6Regs.CMPA.bit.CMPA = 0; // Set compare B value

    // Setup compare
    EPwm6Regs.CMPA.bit.CMPA = PWM_PERIOD_SETTING * DUTY_CYCLE;

    // Active high complementary PWMs - Setup the deadband
    EPwm6Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
    //EPwm6Regs.DBCTL.bit.POLSEL = DB_ACTV_LOC;
    EPwm6Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; ////////////////ACTIVE HIGH/LOW//////////////////////////////////////////////////
    EPwm6Regs.DBCTL.bit.IN_MODE = DBA_ALL;
    //Dead time - Prevents switch shoot-through
    EPwm6Regs.DBFED.bit.DBFED = DEAD_TIME_SETTING;
    EPwm6Regs.DBRED.bit.DBRED = DEAD_TIME_SETTING;
    EPwm6_DB_Direction = DB_UP;
    // Interrupt where we will change the deadband
    EPwm6Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event
    EPwm6Regs.ETSEL.bit.INTEN = 1; // Enable INT
    EPwm6Regs.ETPS.bit.INTPRD = ET_3RD; // Generate INT on 3rd event
    }
  • I wouldn't say 'spoon feeding' is a bad thing. Nothing wrong with showing your customers how to use your products. Specially when they are like me, in school working 80 hours a week for free and may never use this again. Here is my working code for the many other people that seem to be asking the same question and feel like they are being fed water with a fork:

    void InitEPwm2()
    {
    EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up
    EPwm2Regs.TBCTL.bit.PRDLD = TB_SHADOW;
    EPwm2Regs.TBPRD = PWM_PERIOD_SETTING; // Set timer period
    EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
    EPwm2Regs.TBPHS.bit.TBPHS = 0x0000; // Phase is 0
    EPwm2Regs.TBCTR = 0x0000;// Clear counter
    EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; // sync output pulse for pwm6 when ctr = 0;
    // Setup shadow register load on ZERO
    EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
    EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
    // Set Compare values
    EPwm2Regs.CMPA.bit.CMPA = 0; // Set compare A value
    // Set actions
    EPwm2Regs.AQCTLA.bit.ZRO = AQ_SET; // Set PWM1A on Zero
    EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Clear PWM1A on event A, up count

    // Setup compare
    EPwm2Regs.CMPA.bit.CMPA = PWM_PERIOD_SETTING * dutyCycle;

    // Active High complementary PWMs - setup the deadband
    EPwm2Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
    //EPwm2Regs.DBCTL.bit.POLSEL = DB_ACTV_LOC;
    EPwm2Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; ////////////////ACTIVE LOW/HIGH/////////////////////////////////////////////////
    EPwm2Regs.DBCTL.bit.IN_MODE = DBA_ALL;
    //Dead time - Prevents switch shoot-through
    EPwm2Regs.DBFED.bit.DBFED = DEAD_TIME_SETTING;
    EPwm2Regs.DBRED.bit.DBRED = DEAD_TIME_SETTING;
    EPwm2_DB_Direction = DB_UP;
    // Interrupt where we will modify the deadband
    EPwm2Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event
    EPwm2Regs.ETSEL.bit.INTEN = 1; // Enable INT
    EPwm2Regs.ETPS.bit.INTPRD = ET_3RD; // Generate INT on 3rd event
    }

    void InitEPwm6()
    {
    EPwm6Regs.TBPRD = PWM_PERIOD_SETTING;
    //EPwm6Regs.TBCTL.bit.PHSEN = TB_ENABLE; //no PWM when this is enabled
    EPwm6Regs.TBCTL.bit.PHSEN = TB_DISABLE;
    EPwm6Regs.TBPHS.bit.TBPHS = (PWM_PERIOD_SETTING/2) - 1; // Set Phase register to TBPRD/2
    EPwm6Regs.TBCTR = (PWM_PERIOD_SETTING/2) + (PWM_PERIOD_SETTING/8); //start pulse here
    EPwm6Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Asymmetrical mode
    EPwm6Regs.TBCTL.bit.PRDLD = TB_SHADOW;
    EPwm6Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN; // SYNC INPUT FROM EPWM1
    EPwm6Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
    EPwm6Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // load on CTR=Zero
    EPwm6Regs.AQCTLA.bit.ZRO = AQ_SET; // Set PWM1A on Zero
    EPwm6Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Clear PWM1A on event A, up count
    EPwm6Regs.CMPA.bit.CMPA = 0; // Set compare B value

    // Setup compare
    EPwm6Regs.CMPA.bit.CMPA = PWM_PERIOD_SETTING * dutyCycle; //end pulse here

    // Active high complementary PWMs - Setup the deadband
    EPwm6Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
    //EPwm6Regs.DBCTL.bit.POLSEL = DB_ACTV_LOC;
    EPwm6Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; ////////////////ACTIVE HIGH/LOW//////////////////////////////////////////////////
    EPwm6Regs.DBCTL.bit.IN_MODE = DBA_ALL;
    //Dead time - Prevents switch shoot-through
    EPwm6Regs.DBFED.bit.DBFED = DEAD_TIME_SETTING;
    EPwm6Regs.DBRED.bit.DBRED = DEAD_TIME_SETTING;
    EPwm6_DB_Direction = DB_UP;
    // Interrupt where we will change the deadband
    EPwm6Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event
    EPwm6Regs.ETSEL.bit.INTEN = 1; // Enable INT
    EPwm6Regs.ETPS.bit.INTPRD = ET_3RD; // Generate INT on 3rd event
    }
  • Nah.. you got me wrong. I didn't mean in a negative way. Also, I don't work for TI.
    Great that you got it working ! There are number of threads where I've shared the same and people got it working. E2E Search is a very effective tool which you can use and get your issues resolved without even posting anything.
    Sometimes harsh words help you conquer the un-conquered! That's all I wanted :)

    Goodluck & Regards,
    Gautam

  • I got that from the positive emoji. No worries, just a little banter. Thanks for the help.