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.
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!
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?...
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.