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 now one project with 8 PWMs and seems to have a problem with HRPWM, namely with MEP_ScaleFaktor.
I use AUTOCONV function and SFO_v8.lib, but on oscillograms I see, that the MEP_ScaleFaktor is probebly calculated only for 1st PWM-Module.
(By 20kHz PWM-frequency)
Without HR funсtion and duty cycle = 40.5% I've become 59.521% for all channels (I am working with inverted signal)
With HR function and duty cycle = 40.5% I've become 59.50% for first PWM and 59.521 for all other.
The question is - how could I calculate MEP_ScaleFaktor for other channels?
I use this initialization of PWM and call "while (SFO() == 0) {};" funktion one time in "main" and one time in "while()" cycles.
--------------------------------------------------------------------------------------------------------------------
Uint16 j;
for(j=0;j<8;j++)
{
(*ePWM[j]).AQSFRC.bit.RLDCSF = 3;
// Freqünzeinstellung
(*ePWM[j]).TBPRD = PeriodeHalb;
(*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); // initialize HRPWM extension
(*ePWM[j]).AQCTLA.bit.CAU = AQ_SET;
(*ePWM[j]).AQCTLA.bit.CAD = AQ_CLEAR;
(*ePWM[j]).AQCTLB.bit.CAU = AQ_CLEAR;
(*ePWM[j]).AQCTLB.bit.CAD = AQ_SET;
//HRPWM
EALLOW;
(*ePWM[j]).HRCNFG.all = 0x0;
(*ePWM[j]).HRCNFG.bit.EDGMODE = HR_BEP; // MEP control on both edges.
(*ePWM[j]).HRCNFG.bit.CTLMODE = HR_CMP; // CMPAHR and TBPRDHR HR control.
(*ePWM[j]).HRCNFG.bit.HRLOAD = HR_CTR_ZERO_PRD; // load on CTR = 0 and CTR = TBPRD
// (*ePWM[j]).HRCNFG.bit.EDGMODEB = HR_BEP; // MEP control on both edges
// (*ePWM[j]).HRCNFG.bit.CTLMODEB = HR_CMP; // CMPBHR and TBPRDHR HR control
// (*ePWM[j]).HRCNFG.bit.HRLOADB = HR_CTR_ZERO_PRD; // load on CTR = 0 and CTR = TBPRD
(*ePWM[j]).HRCNFG.bit.AUTOCONV = 1; // Enable autoconversion for HR period
(*ePWM[j]).HRPCTL.bit.TBPHSHRLOADE = 1; // Enable TBPHSHR sync (required for updwncount HR control)
(*ePWM[j]).HRPCTL.bit.HRPE = 1; // Turn on high-resolution period control.
(*ePWM[j]).TBCTL.bit.SWFSYNC = 1; // Synchronize high resolution phase to start HR period
EDIS;
// Dead-Band
(*ePWM[j]).DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // Totzeit auf Kanal A und B
(*ePWM[j]).DBCTL.bit.POLSEL = DB_ACTV_LOC; // Ausgänge High Active, A zu B entgegengesetzt
(*ePWM[j]).DBCTL.bit.IN_MODE = DBA_ALL; // Kanal A ist Grundlage für Totzeit Erzeugung
(*ePWM[j]).DBCTL.bit.OUTSWAP = 3; // Kanal A & B vertauschen, damit Ausschalten der Totzeiterzeugung bei nicht Rückwärtsleitung (d.h. keine Invertierung) noch korrekte PWM liefert
(*ePWM[j]).DBRED.bit.DBRED = TOTZEIT;
(*ePWM[j]).DBREDHR.bit.DBREDHR = 0;
(*ePWM[j]).DBFED.bit.DBFED = TOTZEIT;
(*ePWM[j]).DBFEDHR.bit.DBFEDHR = 0;
(*ePWM[j]).HRCNFG2.bit.EDGMODEDB = HR_BEP; // DBREDHR and DBFEDHR
(*ePWM[j]).HRCNFG2.bit.CTLMODEDBRED = 0; // Load on ZRO
(*ePWM[j]).HRCNFG2.bit.CTLMODEDBFED = 0; // Load on ZRO
// ADC
(*ePWM[j]).ETSEL.bit.SOCAEN = 0;
(*ePWM[j]).ETSEL.bit.SOCASEL = 2;
(*ePWM[j]).ETPS.bit.SOCAPRD = 1;
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;
}
}
-----------------------------------------------------------------------------------------------------------------------------
and this struct I am using for tacting: (D is changing between 0 and 1)
-----------------------------------------------------------------------------------------------------------------------------
for(i=0;i<Moduls;i++)
{
temp = (D*(*ePWM[i]).TBPRD);
CMPAHRref = modff(temp, &CMPAref);
(*ePWM[i]).CMPA.all = ((long)CMPAref)<<16 | (long)CMPAHRref<<8;
}
------------------------------------------------------------------------------------------------------------------------------
Thank you in advance!
Hello Anton,
First of all, I see an issue with the HRCNFG[CTLMODE] configuration in your code. This bit should be set to 0, to allow hi-res duty control with hi-res phase shift control. This should fix a lot, if not all, of the issues you are seeing with duty cycle mismatches.
Second, is the PWM output frequency fixed or variable? If it is variable, please refer to the example in C2000Ware located at <path_to_C2000Ware>\device_support\f2837xd\examples\cpu1\hrpwm_deadband_sfo_v8.
This example implements HRPRD (hi-res period), HRDUTY (hi-res duty), HRPHS (hi-res phase shift) and HRDB (hi-res dead-band) simultaneously without any of the TBPHSHR issues you are seeing.
I hope this helps.
Hrishi
Hi Anton,
I am sorry I missed your main question in the first post (i.e. "how could I calculate MEP_ScaleFaktor for other channels?") and instead focused on the code itself.
The MEP scale factor is the same for all PWMs on the device. Please enable AUTOCONV for all PWMs and this will be taken care of by the PWM logic on the device. When AUTOCONV is enabled, the fractional HR value should be written to the CMPAHR register as follows. (remember only most significant 8-bits of CMPAHR are used for this):
To write a fractional value of 0.2 calculate 0.2*(0xFF00) = 0x3300. This value should then be written to CMPAHR.
Also, if you are not using high resolution frequency control, please disable HRPE.
I hope this helps.
Hrishi