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: Action Qualifier Continuous S/W Force (AQCSFRC) Register and PWM first pulse

Part Number: TMS320F28379D

Tool/software: Code Composer Studio

Hello everyone, 

I am making a Program in which I use commands:

EPwm1Regs.AQCSFRC.bit.CSFA = 0; 

EPwm1Regs.AQCSFRC.bit.CSFB = 0;

EPwm1Regs.AQCSFRC.bit.CSFA = 2; 

EPwm1Regs.AQCSFRC.bit.CSFB = 2;

to control PWM output. The problem, that I have encountered is the first PWM pulse after the switching PWM on with:

EPwm1Regs.AQCSFRC.bit.CSFA = 0; 

EPwm1Regs.AQCSFRC.bit.CSFB = 0;

By default I use the duty cycle of 20% but the first pulse after start seems to be ~50% +-10%.

I want to ask, could I somehow solve this problem? Or this is hardware default so? May be there is some another way to turn quickly PWM on and off?

Thank you in advance!

  • Hi,

    Are you using Immediate mode or Shadow mode for loading of AQCSFRC?
    In immediate mode, a continuous force takes effect on the next TBCLK edge. In shadow mode, a continuous force takes effect on the next TBCLK edge after a shadow load into the active register. To configure shadow mode, use AQSFRC[RLDCSF].

    If you are using immediate mode, then the duty cycle of the first pulse really depends on the time at which the software writes to the register.
    The effect is observed in the very next TBCLK cycle. Hence it's difficult to control the exact duty cycle.
    You can try using shadow mode described above to overcome this.
  • Hmm... I use RLDCSF = 11........ '^^,
    Thank you for your advice! I will try to change it tomorrow.

    I also use HRPWM function, is it possible to use SHADOW registers with HRPWM?...

  • You can try using RLDCSF=0 zero instead.
    HRPWM function should be independent of the AQCSFA configuration.
    Changing RLDCSF alone should not impact HRPWM operation.
  • I have tried the method, that you have suggested
    (I have changed the value of RLDCSF from 3 to 0 and than I have tried with 1 and 2 )
    it's doesn't work... The first pulse is still ~50%.
    Do you have some more suggestions?
  • Can you share your PWM configuration - Action Qualifier settings etc?
  • Yes, sure.
    volatile struct EPWM_REGS *ePWM[]   = { &EPwm1Regs, &EPwm2Regs, &EPwm3Regs, &EPwm4Regs, &EPwm5Regs, &EPwm6Regs, &EPwm7Regs, &EPwm8Regs};

    void InitEPwm(Uint32 Period)
    {
    Uint16 j; 
    for(j=0;j<8;j++) 
    {
    (*ePWM[j]).AQSFRC.bit.RLDCSF = 0;

    (*ePWM[j]).TBPRD = Period; 
    (*ePWM[j]).TBCTR = 0x0000;
    (*ePWM[j]).TBCTL.bit.PRDLD = 0;

    (*ePWM[j]).TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;
    (*ePWM[j]).TBCTL.bit.HSPCLKDIV = TB_DIV1;
    (*ePWM[j]).TBCTL.bit.CLKDIV = TB_DIV1; 

    (*ePWM[j]).CMPCTL.bit.SHDWAMODE = CC_SHADOW;
    (*ePWM[j]).CMPCTL.bit.SHDWBMODE = CC_SHADOW;
    (*ePWM[j]).CMPCTL.bit.LOADAMODE = CC_CTR_ZERO_PRD;
    (*ePWM[j]).CMPCTL.bit.LOADBMODE = CC_CTR_ZERO_PRD;

    (*ePWM[j]).CMPA.bit.CMPA = (*ePWM[j]).TBPRD/2; 
    (*ePWM[j]).CMPA.bit.CMPAHR = (1 << 8); 

    (*ePWM[j]).AQCTLA.bit.CAU = AQ_CLEAR; 
    (*ePWM[j]).AQCTLA.bit.CAD = AQ_SET; 

    (*ePWM[j]).AQCTLB.bit.CAU = AQ_SET;
    (*ePWM[j]).AQCTLB.bit.CAD = AQ_CLEAR;

    EALLOW;

    (*ePWM[j]).HRCNFG.all = 0x0;
    (*ePWM[j]).HRCNFG.bit.EDGMODE = HR_BEP;
    (*ePWM[j]).HRCNFG.bit.CTLMODE = HR_CMP;
    (*ePWM[j]).HRCNFG.bit.HRLOAD = HR_CTR_ZERO_PRD;
    (*ePWM[j]).HRCNFG.bit.EDGMODEB = HR_BEP;
    (*ePWM[j]).HRCNFG.bit.CTLMODEB = HR_CMP;
    (*ePWM[j]).HRCNFG.bit.HRLOADB = HR_CTR_ZERO_PRD; 
    (*ePWM[j]).HRCNFG.bit.AUTOCONV = 1;

    (*ePWM[j]).HRPCTL.bit.TBPHSHRLOADE = 1;
    (*ePWM[j]).HRPCTL.bit.HRPE = 0;

    (*ePWM[j]).DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
    (*ePWM[j]).DBCTL.bit.POLSEL = DB_ACTV_HIC;
    (*ePWM[j]).DBCTL.bit.IN_MODE = DBA_ALL;
    (*ePWM[j]).DBCTL.bit.OUTSWAP = 3;
    (*ePWM[j]).DBCTL.bit.HALFCYCLE = 1;
    (*ePWM[j]).DBFEDHR.bit.DBFEDHR = (0 << 9);
    (*ePWM[j]).DBFEDHR.bit.DBFEDHR = (0 << 9);

    DBref = ((long)(TOTZEIT+0))>>15; // Convert to IQ0 (need for DBRED/DBFED they are because High-Byte) (the whole part)
    DBtemp = (TOTZEIT+0) - ((long)DBref<<15); // Separation of a fractal
    DBHRref = DBtemp<<1; // convert to Q16 // Writing only fractal part in high bits of DBHRRED/DBHRFED

    (*ePWM[j]).DBRED.bit.DBRED = DBref;
    (*ePWM[j]).DBREDHR.bit.DBREDHR = DBHRref;
    (*ePWM[j]).DBFED.bit.DBFED = DBref;
    (*ePWM[j]).DBFEDHR.bit.DBFEDHR = DBHRref;

    (*ePWM[j]).HRCNFG2.bit.EDGMODEDB = HR_BEP;
    (*ePWM[j]).HRCNFG2.bit.CTLMODEDBRED = 0; // Load on ZRO
    (*ePWM[j]).HRCNFG2.bit.CTLMODEDBFED = 0; // Load on ZRO

    (*ePWM[j]).ETSEL.bit.SOCAEN = 1;
    (*ePWM[j]).ETSEL.bit.SOCASEL = 2;
    (*ePWM[j]).ETPS.bit.SOCAPRD = 2;

    if(j==0)
    {
    (*ePWM[j]).TBPHS.bit.TBPHS = 0;
    (*ePWM[j]).TBCTL.bit.SYNCOSEL = TB_CTR_ZERO;
    (*ePWM[j]).TBCTL.bit.PHSEN = TB_DISABLE;
    }
    else
    {
    (*ePWM[j]).TBCTL.bit.SYNCOSEL = TB_SYNC_IN;
    (*ePWM[j]).TBCTL.bit.PHSEN = TB_ENABLE;
    }
    EDIS;

    (*ePWM[j]).TBCTL.bit.SWFSYNC = 1;
    }

    }

    This function I use to turn on and offthe PWM channels, that I need. 

    void UpdateModule(int VALUE)
    {
    Uint16 j;

    if(VALUE > VALUE_MAX)
    {
    VALUE = VALUE_MAX;
    }
    if(VALUE < 0)
    {
    VALUE = 0;
    }

    for(j=0;j<VALUE;j++)
    {
    (*Regulator[j]).ui = DC; 
    D_MOD[j] = DC; 

    if(j<=(VALUE)/2) 
    {

    PHS1 = (*ePWM[j]).TBPRD*2/(float)VALUE*j;
    IQPHS1 = PHS1 * 32768;
    PHSref = (long)(IQPHS1)>>15;
    PHStemp = (IQPHS1) - ((long)PHSref<<15);
    PHSHRref = PHStemp<<1;
    (*ePWM[0]).TBPHS.all = 0;
    (*ePWM[j]).TBPHS.bit.TBPHS = PHSref;
    (*ePWM[j]).TBPHS.bit.TBPHSHR = PHSHRref;

    (*ePWM[j]).TBCTL.bit.PHSDIR = TB_DOWN;

    }


    else
    {
    PHS2 = (float)((*ePWM[j]).TBPRD*2 - ((*ePWM[j]).TBPRD*2/(float)VALUE*j));
    IQPHS2 = PHS2 * 32768;
    PHSref = (long)(IQPHS2)>>15;
    PHStemp = (IQPHS2) - ((long)PHSref<<15);
    PHSHRref = PHStemp<<1;
    (*ePWM[0]).TBPHS.all = 0;
    (*ePWM[j]).TBPHS.bit.TBPHS = PHSref;
    (*ePWM[j]).TBPHS.bit.TBPHSHR = PHSHRref;

    (*ePWM[j]).TBCTL.bit.PHSDIR = TB_UP;
    }

    if(FLAG_Bidirect != 1)
    {
    if(I_ref >= 0 )
    {
    (*ePWM[j]).AQCSFRC.bit.CSFB = 2;
    (*ePWM[j]).AQCSFRC.bit.CSFA = 0;
    (*ePWM[j]).DBCTL.bit.OUT_MODE = DB_DISABLE;
    (*ePWM[j]).DBCTL.bit.OUTSWAP = 0;

    }
    else
    {
    (*ePWM[j]).AQCSFRC.bit.CSFA = 2;
    (*ePWM[j]).AQCSFRC.bit.CSFB = 0;
    (*ePWM[j]).DBCTL.bit.OUT_MODE = DB_DISABLE;
    (*ePWM[j]).DBCTL.bit.OUTSWAP = 0; 

    }
    }
    else
    {
    (*ePWM[j]).DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
    (*ePWM[j]).DBCTL.bit.OUTSWAP = 3;
    (*ePWM[j]).AQCSFRC.bit.CSFA = 0;
    (*ePWM[j]).AQCSFRC.bit.CSFB = 0;
    }

    }

    if(I_ref >= 0)

    for(j=VALUE;j<8;j++)
    {
    (*ePWM[j]).AQCSFRC.bit.CSFA = 2;
    (*ePWM[j]).AQCSFRC.bit.CSFB = 2;
    (*ePWM[j]).DBCTL.bit.OUT_MODE = 0;
    }

    for(j=VALUE; j<VALUE_MAX; j++)
    {
    D_MOD[j] = DC;
    (*Regulator[j]).Ref = 0;
    (*Regulator[j]).Fbk = 0;
    (*Regulator[j]).err_old = 0;
    (*Regulator[j]).Stoer = 0;
    (*Regulator[j]).Out = 0;
    (*Regulator[j]).up = 0;
    (*Regulator[j]).ui = 0;
    (*Regulator[j]).v1 = 0;
    (*Regulator[j]).err = 0;
    }

    }

  • Hi,

    I tried similar configuration and unable to replicate the condition you mentioned above.
    I do observe that the duty cycle is as expected even in the first cycle after CSFA is zero.
    For the sake of root causing this issue, can you disable the Sync operation and check?
    I do see that you are switching between PHSEN On/Off conditions. Can you keep it Off always and check.
    I wonder if the unexpected duty on the first  PWM cycle is being caused by some other configuration and not merely CSFA change.

  • Anton,
    It has been some time since your last reply, If you are still facing this issue, please address Bharathi's questions so that we can continue the debug.
    Thanks,
    Mark
  • The problem seems to be in phase shifting operations...
    Since that another way to walk this problem around was found, I would leave it now for some time.
    Thanks all for help!