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.

TMS320F28377S: HRPWM period/phase control

Part Number: TMS320F28377S

I am trying to use PWM 6,7,8.

PWM6 and PWM7 will run nominally at 125000 Hz and PWM8 run at a frequency 4x PWM6 and PWM7. This is a variable frequency application using HR period control.

PWM 8 is the trigger to the ADC and is required to be phase synchronized to PWM6 and PWM7.

Every time I change the frequency of all 3 PWMs, I loose phase synchronization from PWM8 to PWM6 and PWM7. Some frequencies will cause PWM6 and PWM7 and PWM8 to be phase aligned but most will not.

Am I doing something wrong when I change frequency or is it my initialization?

below is my frequency setting code followed by the PWM initialization:

#define RESONATE_PWM_LEFT EPwm6Regs
#define RESONATE_PWM_RIGHT EPwm7Regs
#define ADC_PWM EPwm8Regs

void H_bridge_set_frequency_registers(uint32_t freq)
{
uint32_t integer;
uint32_t frac;
uint32_t period;
uint32_t ADC_period = 0;
float freq_f = freq;

if (freq >= 10000 && freq <= 320000)
{

//convert freq to period
period = 25600000000.0/freq_f;
//get the period calculated and divide by 4 for ADC sample frequency
ADC_period = (period >> 2);
integer = (ADC_period >> 8);
//mask off the fraction
frac = (ADC_period & 0xFF);
//set ADC freq as 4 times pwm period
ADC_PWM.TBPRD = integer-1;
ADC_PWM.TBPRDHR = (frac << 8);

frac = (period & 0xFF);
integer = (period >> 8);
//set PWM out freq

RESONATE_PWM_LEFT.TBPRD = integer-1;
RESONATE_PWM_LEFT.TBPRDHR = (frac << 8);

RESONATE_PWM_RIGHT.TBPRD = integer-1;
RESONATE_PWM_RIGHT.TBPRDHR = (frac << 8);
}

}

void resonate_left_PWM_setup(void)
{
int period = 800;
RESONATE_PWM_LEFT.TBCTL.bit.PRDLD = TB_SHADOW; // set Shadow load
RESONATE_PWM_LEFT.TBCTL.bit.PHSEN = 0;
RESONATE_PWM_LEFT.TBPRD = period-1; // PWM frequency = 1/(2*TBPRD)
RESONATE_PWM_LEFT.CMPA.bit.CMPA = period / 2; // set duty 50% initially
RESONATE_PWM_LEFT.CMPA.bit.CMPAHR = (1 << 8); // initialize HRPWM extension
RESONATE_PWM_LEFT.CMPB.bit.CMPB = period / 2; // set duty 50% initially
RESONATE_PWM_LEFT.CMPB.all |= 1;
RESONATE_PWM_LEFT.TBPHS.all = 0;
RESONATE_PWM_LEFT.TBCTR = 0;

RESONATE_PWM_LEFT.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Select up count mode
RESONATE_PWM_LEFT.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO;
RESONATE_PWM_LEFT.TBCTL.bit.HSPCLKDIV = TB_DIV1;
RESONATE_PWM_LEFT.TBCTL.bit.CLKDIV = TB_DIV1; // TBCLK = SYSCLKOUT
RESONATE_PWM_LEFT.TBCTL.bit.FREE_SOFT = 11;

RESONATE_PWM_LEFT.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // LOAD CMPA on CTR = 0
RESONATE_PWM_LEFT.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
RESONATE_PWM_LEFT.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
RESONATE_PWM_LEFT.CMPCTL.bit.SHDWBMODE = CC_SHADOW;

RESONATE_PWM_LEFT.AQCTLA.bit.ZRO = AQ_SET; // PWM toggle high/low
RESONATE_PWM_LEFT.AQCTLA.bit.CAU = AQ_CLEAR;
RESONATE_PWM_LEFT.AQCTLB.bit.ZRO = AQ_SET; // PWM toggle high/low
RESONATE_PWM_LEFT.AQCTLB.bit.CBU = AQ_CLEAR;

RESONATE_PWM_LEFT.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // enable Dead-band module
RESONATE_PWM_LEFT.DBCTL.bit.POLSEL = DB_ACTV_HIC; // Active Hi complementary
RESONATE_PWM_LEFT.DBCTL.bit.IN_MODE = DBA_ALL; // EPWM1A is source for both delays

RESONATE_PWM_LEFT.DBFED.bit.DBFED = 10;
RESONATE_PWM_LEFT.DBRED.bit.DBRED = 10;

EALLOW;
RESONATE_PWM_LEFT.HRCNFG.all = 0x0;
RESONATE_PWM_LEFT.HRCNFG.bit.EDGMODE = HR_BEP; // MEP control on both edges.
RESONATE_PWM_LEFT.HRCNFG.bit.CTLMODE = HR_CMP; // CMPAHR and TBPRDHR HR control.
RESONATE_PWM_LEFT.HRCNFG.bit.HRLOAD = HR_CTR_ZERO; // load on CTR = 0 and CTR = TBPRD
RESONATE_PWM_LEFT.HRCNFG.bit.EDGMODEB = HR_BEP; // MEP control on both edges
RESONATE_PWM_LEFT.HRCNFG.bit.CTLMODEB = HR_CMP; // CMPBHR and TBPRDHR HR control
RESONATE_PWM_LEFT.HRCNFG.bit.HRLOADB = HR_CTR_ZERO; // load on CTR = 0 and CTR = TBPRD
RESONATE_PWM_LEFT.HRCNFG.bit.AUTOCONV = 1; // Enable autoconversion for HR period

//RESONATE_PWM_LEFT.HRPCTL.bit.TBPHSHRLOADE = 1; // Enable TBPHSHR sync (required for updwn count HR control)
RESONATE_PWM_LEFT.HRPCTL.bit.HRPE = 1; // Turn on high-resolution period control.


EDIS;
}

void resonate_right_PWM_setup(void)
{
int period = 800;
RESONATE_PWM_RIGHT.TBCTL.bit.PRDLD = TB_SHADOW; // set Shadow load
RESONATE_PWM_RIGHT.TBCTL.bit.PHSEN = TB_ENABLE;
RESONATE_PWM_RIGHT.TBPRD = period-1; // PWM frequency = 1/(2*TBPRD)
RESONATE_PWM_RIGHT.CMPA.bit.CMPA = period / 2; // set duty 50% initially
RESONATE_PWM_RIGHT.CMPA.bit.CMPAHR = (1 << 8); // initialize HRPWM extension
RESONATE_PWM_RIGHT.CMPB.bit.CMPB = period / 2; // set duty 50% initially
RESONATE_PWM_RIGHT.CMPB.all |= 1;
RESONATE_PWM_RIGHT.TBPHS.all = 0;
RESONATE_PWM_RIGHT.TBCTR = 0;

RESONATE_PWM_RIGHT.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Select up count mode
RESONATE_PWM_RIGHT.TBCTL.bit.SYNCOSEL = TB_SYNC_IN;
RESONATE_PWM_RIGHT.TBCTL.bit.HSPCLKDIV = TB_DIV1;
RESONATE_PWM_RIGHT.TBCTL.bit.CLKDIV = TB_DIV1; // TBCLK = SYSCLKOUT
RESONATE_PWM_RIGHT.TBCTL.bit.FREE_SOFT = 11;

RESONATE_PWM_RIGHT.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // LOAD CMPA on CTR = 0
RESONATE_PWM_RIGHT.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
RESONATE_PWM_RIGHT.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
RESONATE_PWM_RIGHT.CMPCTL.bit.SHDWBMODE = CC_SHADOW;

RESONATE_PWM_RIGHT.AQCTLA.bit.ZRO = AQ_CLEAR; // PWM toggle high/low
RESONATE_PWM_RIGHT.AQCTLA.bit.CAU = AQ_SET;
RESONATE_PWM_RIGHT.AQCTLB.bit.ZRO = AQ_CLEAR; // PWM toggle high/low
RESONATE_PWM_RIGHT.AQCTLB.bit.CBU = AQ_SET;

RESONATE_PWM_RIGHT.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // enable Dead-band module
RESONATE_PWM_RIGHT.DBCTL.bit.POLSEL = DB_ACTV_HIC; // Active Hi complementary
RESONATE_PWM_RIGHT.DBCTL.bit.IN_MODE = DBA_ALL; // EPWM1A is source for both delays

RESONATE_PWM_RIGHT.DBFED.bit.DBFED = 10;
RESONATE_PWM_RIGHT.DBRED.bit.DBRED = 10;

EALLOW;
RESONATE_PWM_RIGHT.HRCNFG.all = 0x0;
RESONATE_PWM_RIGHT.HRCNFG.bit.EDGMODE = HR_BEP; // MEP control on both edges.
RESONATE_PWM_RIGHT.HRCNFG.bit.CTLMODE = HR_CMP; // CMPAHR and TBPRDHR HR control.
RESONATE_PWM_RIGHT.HRCNFG.bit.HRLOAD = HR_CTR_ZERO; // load on CTR = 0 and CTR = TBPRD
RESONATE_PWM_RIGHT.HRCNFG.bit.EDGMODEB = HR_BEP; // MEP control on both edges
RESONATE_PWM_RIGHT.HRCNFG.bit.CTLMODEB = HR_CMP; // CMPBHR and TBPRDHR HR control
RESONATE_PWM_RIGHT.HRCNFG.bit.HRLOADB = HR_CTR_ZERO; // load on CTR = 0 and CTR = TBPRD
RESONATE_PWM_RIGHT.HRCNFG.bit.AUTOCONV = 1; // Enable autoconversion for HR period

RESONATE_PWM_RIGHT.HRPCTL.bit.TBPHSHRLOADE = 1; // Enable TBPHSHR sync (required for updwn count HR control)
RESONATE_PWM_RIGHT.HRPCTL.bit.HRPE = 1; // Turn on high-resolution period control.


EDIS;
}

void ADC_PWM_setup(void)
{
int period = 200;
ADC_PWM.ETSEL.bit.SOCAEN = 0; // Disable SOC on A group
ADC_PWM.ETSEL.bit.SOCASEL = 4; // Select SOC on up-count
ADC_PWM.ETPS.bit.SOCAPRD = 1; // Generate pulse on 1st event

ADC_PWM.TBCTL.bit.PRDLD = TB_SHADOW; // set Shadow load
ADC_PWM.TBCTL.bit.PHSEN = TB_ENABLE;
ADC_PWM.TBPRD = period-1; // PWM frequency = 1/(2*TBPRD)
ADC_PWM.CMPA.bit.CMPA = period / 2; // set duty 50% initially
ADC_PWM.CMPA.bit.CMPAHR = (0 << 8); // initialize HRPWM extension
ADC_PWM.CMPB.bit.CMPB = period / 2; // set duty 50% initially
ADC_PWM.CMPB.all |= 1;
ADC_PWM.TBPHS.all = 0;
ADC_PWM.TBCTR = 0;

ADC_PWM.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Select up count mode
ADC_PWM.TBCTL.bit.SYNCOSEL = TB_SYNC_IN;
ADC_PWM.TBCTL.bit.HSPCLKDIV = TB_DIV1;
ADC_PWM.TBCTL.bit.CLKDIV = TB_DIV1; // TBCLK = SYSCLKOUT
//EPwm4Regs.TBCTL.bit.FREE_SOFT = 11;

ADC_PWM.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // LOAD CMPA on CTR = 0
ADC_PWM.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
ADC_PWM.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
ADC_PWM.CMPCTL.bit.SHDWBMODE = CC_SHADOW;

ADC_PWM.AQCTLA.bit.ZRO = AQ_SET; // PWM toggle high/low
ADC_PWM.AQCTLA.bit.CAU = AQ_CLEAR;
ADC_PWM.AQCTLB.bit.ZRO = AQ_SET; // PWM toggle high/low
ADC_PWM.AQCTLB.bit.CBU = AQ_CLEAR;

ADC_PWM.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // enable Dead-band module
ADC_PWM.DBCTL.bit.POLSEL = DB_ACTV_HIC; // Active Hi complementary
ADC_PWM.DBCTL.bit.IN_MODE = DBA_ALL; // EPWM1A is source for both delays

//EPwm4Regs.DBFED.bit.DBFED = 10;
//EPwm4Regs.DBRED.bit.DBRED = 10;

EALLOW;
ADC_PWM.HRCNFG.all = 0x0;
ADC_PWM.HRCNFG.bit.EDGMODE = HR_BEP; // MEP control on both edges.
ADC_PWM.HRCNFG.bit.CTLMODE = HR_CMP; // CMPAHR and TBPRDHR HR control.
ADC_PWM.HRCNFG.bit.HRLOAD = HR_CTR_ZERO; // load on CTR = 0 and CTR = TBPRD
ADC_PWM.HRCNFG.bit.EDGMODEB = HR_BEP; // MEP control on both edges
ADC_PWM.HRCNFG.bit.CTLMODEB = HR_CMP; // CMPBHR and TBPRDHR HR control
ADC_PWM.HRCNFG.bit.HRLOADB = HR_CTR_ZERO; // load on CTR = 0 and CTR = TBPRD
ADC_PWM.HRCNFG.bit.AUTOCONV = 1; // Enable autoconversion for HR period

ADC_PWM.HRPCTL.bit.TBPHSHRLOADE = 1; // Enable TBPHSHR sync (required for updwn count HR control)
ADC_PWM.HRPCTL.bit.HRPE = 1; // Turn on high-resolution period control.
//ADC_PWM.TBCTL.bit.SWFSYNC = 1;

EDIS;

}

  • Hi Chris,

    While I take a look at your code could you please let me know when your H_bridge_set_frequency_registers() function gets called or where in the process this is happening?

    Best Regards,

    Marlyn

  • H_bridge_set_frequency_registers() is called when the user changes frequency by command.

  • Chris,

    When posting your code please use the correct formatting. There is a code element you can post your code in. Also please only post snippet of the code you suspect is not working.

    1. For your application is using both High resolution period and high resolution phase required?

    2. I recommend picking either high resolution period or high resolution phase. The two modes are not meant to work at the same time.

    Nima

  • void H_bridge_set_frequency_registers(uint32_t freq)
    {
      uint32_t integer;
      uint32_t frac;
      uint32_t period;
      uint32_t ADC_period = 0;
      float freq_f = freq;
    
      if (freq >= 10000 && freq <= 320000)
      {
    
        //convert freq to period
        period = 25600000000.0/freq_f;
        //get the period calculated and divide by 4 for ADC sample frequency
        ADC_period = (period >> 2);
        integer = (ADC_period >> 8);
        //mask off the fraction
        frac = (ADC_period & 0xFF);
        //set ADC freq as 4 times pwm period
        ADC_PWM.TBPRD = integer-1;
        ADC_PWM.TBPRDHR = (frac << 8);
    
        frac = (period & 0xFF);
        integer = (period >> 8);
        //set PWM out freq
    
        RESONATE_PWM_LEFT.TBPRD = integer-1;
        RESONATE_PWM_LEFT.TBPRDHR = (frac << 8);
    
        RESONATE_PWM_RIGHT.TBPRD = integer-1;
        RESONATE_PWM_RIGHT.TBPRDHR = (frac << 8);
      }
    
    }

  • Have you configured the sync chain as  has indicated above?

    For HR period, you have to select HR DUTY control mode and enable the HRPE bit.

    Do not use HR PHASE mode.

  • Yes period control is selected for all PWM as seen my initialization code above.

    Yes I also set the HRPE bit

    EALLOW;
    RESONATE_PWM_LEFT.HRCNFG.all = 0x0;
    RESONATE_PWM_LEFT.HRCNFG.bit.EDGMODE = HR_BEP; // MEP control on both edges.
    RESONATE_PWM_LEFT.HRCNFG.bit.CTLMODE = HR_CMP; // CMPAHR and TBPRDHR HR control.
    RESONATE_PWM_LEFT.HRCNFG.bit.HRLOAD = HR_CTR_ZERO; // load on CTR = 0 and CTR = TBPRD
    RESONATE_PWM_LEFT.HRCNFG.bit.EDGMODEB = HR_BEP; // MEP control on both edges
    RESONATE_PWM_LEFT.HRCNFG.bit.CTLMODEB = HR_CMP; // CMPBHR and TBPRDHR HR control
    RESONATE_PWM_LEFT.HRCNFG.bit.HRLOADB = HR_CTR_ZERO; // load on CTR = 0 and CTR = TBPRD
    RESONATE_PWM_LEFT.HRCNFG.bit.AUTOCONV = 1; // Enable autoconversion for HR period
    
    //RESONATE_PWM_LEFT.HRPCTL.bit.TBPHSHRLOADE = 1; // Enable TBPHSHR sync (required for updwn count HR control)
    RESONATE_PWM_LEFT.HRPCTL.bit.HRPE = 1; // Turn on high-resolution period control.
    
    
    EDIS;

    I have also configured the sync chain by setting all PWMs SYNCOSEL = TB_SYNC_IN and also setting TBCTL.bit.PHSEN = 1 on the slave PWMs.

  • Hi Chris,

    Please take a look at the following document: Multi-phase Variable Frequency.pdf

    It describes that when you have a variable frequency application its best to perform the updates to PRD within a PWM ISR which should be configured to a known good point in the switching cycle. Within your H_bridge_set_frequency_registers() calculate the new values for the PRD registers but instead of writing the values to the ePWM registers there, enable a EPWM ISR and update the PRD registers within the ISR. Once you've updated the PRD values in the ISR disable the ISR. Please try the process outlined in this document and let me know the outcome.

    Best Regards,

    Marlyn