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.

TMS320F28069: phase shift problem

Part Number: TMS320F28069


Hi, my customer is configuring PWM1 and PWM2 and would like them to have 180° phase shift.

static void vSetEpwm1(void)

{

    EPwm1Regs.TBPRD = PwmPeriod>>1;

    EPwm1Regs.CMPA.half.CMPA = PwmPeriod>>2;

    EPwm1Regs.TBPHS.half.TBPHS = 0;

    EPwm1Regs.TBCTR = 0;

    EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;

    EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;

    EPwm1Regs.TBCTL.bit.PHSDIR = TB_UP;

    EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW;

    EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO;

    EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;            //TBCLK=SYSCLKOUT

    EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;

 

    EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;

    EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;

    EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO_PRD;

    EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO_PRD;

 

    EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;

    EPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR;

    EPwm1Regs.AQSFRC.bit.RLDCSF = 0;                    // AQCSFRC load on zero

 

    EPwm1Regs.DBCTL.bit.IN_MODE = DBA_ALL;

    EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_LOC;

    EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;

 

    EPwm1Regs.DBRED = DeadBand;

    EPwm1Regs.DBFED = DeadBand;

 

    EPwm1Regs.ETSEL.bit.SOCAEN = 1;                     // Enable SOC on A group

    EPwm1Regs.ETSEL.bit.SOCASEL = ET_CTR_PRD;           // Select SOC on TBPRD

    EPwm1Regs.ETPS.bit.SOCAPRD = ET_1ST;                // Generate pulse on 1st event

}

 

static void vSetEpwm2(void)

{

    EPwm2Regs.TBPRD = PwmPeriod>>1;

    EPwm2Regs.CMPA.half.CMPA = PwmPeriod>>2;

    EPwm2Regs.TBPHS.half.TBPHS = EPwm2Regs.TBPRD - 1;

    EPwm2Regs.TBCTR = 0;

    EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;

    EPwm2Regs.TBCTL.bit.PHSEN = TB_ENABLE;

    EPwm2Regs.TBCTL.bit.PHSDIR = TB_UP;

    EPwm2Regs.TBCTL.bit.PRDLD = TB_SHADOW;

    EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN;

    EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;            //TBCLK=SYSCLKOUT

    EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV1;

 

    EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;

    EPwm2Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;

    EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO_PRD;

    EPwm2Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO_PRD;

 

    EPwm2Regs.AQCTLA.bit.CAU = AQ_SET;

    EPwm2Regs.AQCTLA.bit.CAD = AQ_CLEAR;

    EPwm2Regs.AQSFRC.bit.RLDCSF = 0;                   // AQCSFRC load on zero

 

    EPwm2Regs.DBCTL.bit.IN_MODE = DBA_ALL;

    EPwm2Regs.DBCTL.bit.POLSEL = DB_ACTV_LOC;

    EPwm2Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;

 

    EPwm2Regs.DBRED = DeadBand;

    EPwm2Regs.DBFED = DeadBand;

 

    EPwm2Regs.ETSEL.bit.SOCAEN = 1;                     // Enable SOC on A group

    EPwm2Regs.ETSEL.bit.SOCASEL = ET_CTR_PRD;          // Select SOC from counter = ZERO

    EPwm2Regs.ETPS.bit.SOCAPRD = ET_1ST;                // Generate pulse on 1st event

}

Most of the time they have 180 phase shift. TBPRD=700. TBPHS of PWM2 is (TBPRD-1) to make the phase shift 180°.

But there are time that PWM2(slave PWM)'s TBCTR will count from 700 to 1400. The data we captured is as below:

blue line- PWM2 TBCTR, purple line- PWM1 TBCTR.

We don't understand why it behaves like this.

  • Howard,

    When using Up-Down count mode you can only shift up to 180 degrees using TBPHS. If you shift beyond this number you need to change the direction of the counter after a sync event using TBCTL.PHSDIR and readjust TBPHS's value. 

    I suspect this may be your problem. Please note that the PWM's counter is very simple, it counts in a direction until it hits TBPRD or 0 and then will change direction and count the the opposite way. In the above case if TBPRD is not 1400 then something in software has been configured to reverse the direction of the counter, I would verify when sync pulses are occurring and what is the programmed TBPHS and PHSDIR at the time of the sync event.

    Regards,
    Cody 

  • Cody,

    The TBPRD is not 1400 but 700.

    My understanding is: even if the software changes the direction, when we hit 700, the counter will start counting down, not up. So it should not exceeds 700 for TBCTR.

    how can we check what is the programmed TBPHS and PHSDIR at exactly the time of the sync event?

    We measured another wrongly TBCTR waveform as below:

    it changes from 700-2100 and always count up(although the same configuration as before).

    line1-blue-TBCTR, line2- RED-TBPRD(700), line3-green-CMPA, line4-purple-TBPHS(699).

  • Howard,

    you should be able to configure an interrupt at the same time as the sync event and store the values... this will be slightly after the event, but should give you a good indication of what they were.

    This graph you shared is exactly the case where you put too high of a value into TBPHS and set it to count up. Any value in TBPHS that is larger than TBPRD can cause an issue. If the PHSDIR is set to count up the TBCTR will count up until the counter overflows or another sync pulse comes in. In your case you receive a sync pulse after 1400 counts so it counts up from 700 to 2100 and resets to 700.

    Please note: that If PHSDIR is set in the down count direction you can still have issues when loading a TBPHS value larger than TBPRD. This is because there is a chance that CMPx events will be missed due to the counter discontinuity. This discontinuity will happen after every sync pulse, so if you sync once per period it will always happen, if you only synchronize at the beginning of your code it will only happen during the first cycle. 

    To avoid this when phase shifting past 180 degrees with up down count mode you must change the counter direction in software and adjust the TBPHS register to be less than TBPRD. For example if TBPHS was 125 and TBPRD was 100, reverse the counter direction and lower TBPHS to 75 [TBPRD-(TBPHS-TBPRD)].

    Regards,
    Cody

  • Cody,

    I'm sorry but in our configuration, TBPHS=699, TBPRD=700. TBPHS<TBPRD so it should not be a problem. And since we need 180 phase shift, we have to set TBPHS as close to TBPRD as possible in up-down count mode as the sync pulse happens on PWM1 count to 0 and it will trigger PWM2 TBCTR to load TBPHS value.

    1. If it's a problem, could you please suggest what's the problem and what's the limit on TBPHS?

    2. With the same configuration, most of the time the TBCTR waveform is correct in fact, but there will be 2 kinds of incorrect waveform, which is the pic I post on the my first conversation(count up from 700 to 1400 and then down to 700) and the pic I post on my reply(count up from 700 to 2100 and then reset to 700). I can't find a explanation to this phenomenon.

  • Howard,

    The simplest fix is to use either up count mode or down count mode not up-down-count mode. These modes are more simple to use when shifting 180 degrees or more. 

    Never the less this is possible with up-down-count mode. When phase shifting 180 degrees or more you must change the counter direction in software if TBPHS >= TBCTR. This is the second case that you are seeing where TBCTR counts from 700 to 2100 the resets to 700.

    As for the first case(where TBCTR counts between 700 and 1400) I must assume that TBPRD or TBPHS must be set at 1400.

    Explanation:

    There are only two things that can cause the CTRDIR to change from count down to count up. The first is TBCTR =0. This does not happen. And the second is a sync event. Knowing this I believe that a sync event is happening when ePWM1's counter= 0 and this causes ePWM2's TBCTR value to be loaded with a value of 700 and count up.

    There are also only two things that can cause the CTRDIR to change from count up to count down. The first is TBCTR= TBPRD, and the second is a sync event when PHSDIR =0.

    If it is TBCTR = TBPRD that is causing the direction of the counter to change you will clearly see TBPRD set to 1400.

    If it is a sync event causing the change then you will see 1400 loaded in TBPHS and PHSDIR = 0.

    Please remember that from my statement above we know it is the sync even causing the change from down count to up count, so a sync pulse is less likely to be the event that is switching the counter from count up to count down. Though it is still possible, but this would require TBPHS and PHSDIR to be loaded twice per period, and I assume that code be easy to see. For this reason start by checking if TBPRD is ever set to 1400 in code.

    Please pause the code execution and evaluate TBPHS, TBPRD, and PHSDIR. These will tell you what is changing the counter direction.

    Regards,
    Cody 

  • Cody,

    for this picture below which TBCTR of PWM2 is counting from 700-1400-700, the TBPRD is the red line, and it's always 700, not 1400 as you see. 

    We get this waveform by using another PWM like PWM8 to generate an ISR and read the registers value, and we plot the data we get and we will get such a plot.

    Another question is: when in up-down count mode, if we set TBPHS=TBPRD and set PHSDIR=1 to count up, but TBCTR=TBPHS=TBPRD will make it count down, this is conflicted, then which one will take priority?

  • Howard,

    Can you please confirm when sync pulses are received by the PWM counting between 700 and 1400? Please also confirm that the PHSDIR value is not changing. A sync event is the only other thing that can change CTRDIR.

    Another question is: when in up-down count mode, if we set TBPHS=TBPRD and set PHSDIR=1 to count up, but TBCTR=TBPHS=TBPRD will make it count down, this is conflicted, then which one will take priority?

    Howard, I don't actually know which event takes priority, but I believe this behavior to be deterministic. My guess is that if you sync to TBCTR=TBPHS=TBPRD that the PHSDIR bit will take priority, but I have not confirmed. If you want the answer to this I will need to ask the design team to simulate. Please let me know.

    Regards,
    Cody 

  • Cody,

    I'm trying to configure watchpoint that will halt the CPU when TBCTR count exceeds 700.

    But I'm not able to do it because it's not a code that write TBCTR value, but the device itself is counting.

    Anyway to halt the CPU when TBCTR count to a specific value with watchpoint(or any other way)?

    How to do it? It's best if you could give me a screenshot of the configuration, thanks.

    Configuration below is not able to achieve my goal.

  • Howard,

    I *believe* that watchpoints only observe the CPU access to locations, so as you have indicated the changes to TBCTR by other mechanisms will not be captured.

    If I were to try and debug this I would periodically pole TBCTR with the C28x core. This can be done wherever convenient, and if you want a regular period the CPU timers, eCAP, or PWMs can be use as a trigger source for the polling code.

    Regards,
    Cody