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: HRPWM Question

Part Number: TMS320F28379D
Other Parts Discussed in Thread: C2000WARE

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!

  • Hi Anton,

    I am looking into this issue. Just a quick check, which all pwm instances you are using in your example as HRPWM is available only for pwm1-pwm8 for this device?

    Thanks
    Vasudha
  • Hi Vasudha,

    Microcontroller has 8 PWM-Channels and I want to use all of them as HRPWM.
    So in code:
    volatile struct EPWM_REGS *ePWM[] = { &EPwm1Regs, &EPwm2Regs, &EPwm3Regs, &EPwm4Regs, &EPwm5Regs, &EPwm6Regs, &EPwm7Regs, &EPwm8Regs};

    Thanks!
  • UPDATE
    I have written a small program for debugging
    -----------------------------------------------------------------------
    //
    // Included Files
    //
    #include "F28x_Project.h"
    #include "SFO_V8.h"
    #include "math.h"

    //
    // Defines
    //
    #define PWM_CH 9 // # of PWM channels for SFO()
    #define MODMAX 8 // # of PWM channels for Program
    //
    // Globals
    //
    float D=0.417, temp, CMPAref, CMPAHRref, ttemp, PHS, PHSHR;

    int Module = 3;
    float t=0, k=0;

    int MEP_ScaleFactor; // Global variable used by the SFO library

    volatile struct EPWM_REGS *ePWM[MODMAX] =
    { &EPwm1Regs, &EPwm2Regs, &EPwm3Regs, &EPwm4Regs, &EPwm5Regs,
    &EPwm6Regs, &EPwm7Regs, &EPwm8Regs};


    void HRPWM_Config(int);

    void main(void)
    {
    int i, j;

    EALLOW; // This is needed to write to EALLOW protected registers

    InitSysCtrl();

    EDIS;

    InitEPwmGpio();

    DINT; // Disable CPU interrupts

    InitPieCtrl();


    EALLOW;
    IER = 0x0000;
    IFR = 0x0000;

    InitPieVectTable();

    EINT; // Enable Global interrupt INTM
    ERTM; // Enable Global realtime interrupt DBGM

    while (SFO() == 0) {} // MEP_ScaleFactor calculated by MEP Cal Module

    HRPWM_Config(2500); // ePWMx target
    while(1)
    {

    for(i=0;i<Module;i++)
    {
    (*ePWM[i]).AQCSFRC.bit.CSFA = 0; // A not trigger
    (*ePWM[i]).AQCSFRC.bit.CSFB = 0; // B not trigger

    if(i<=(Module)/2)
    {
    k = (*ePWM[i]).TBPRD*2/(float)(Module)*i;
    PHSHR = modff(k, &PHS);
    (*ePWM[i]).TBPHS.all = ((long)PHS)<<16 | (long)PHSHR<<8;
    (*ePWM[i]).TBCTL.bit.PHSDIR = TB_DOWN;
    }
    else
    {
    t = (*ePWM[i]).TBPRD*2/(float)Module*i;
    ttemp = (float)((*ePWM[i]).TBPRD*2 - t);
    PHSHR = modff(ttemp, &PHS);
    (*ePWM[i]).TBPHS.all = ((long)PHS)<<16 | (long)PHSHR<<8;
    (*ePWM[i]).TBCTL.bit.PHSDIR = TB_UP;
    }

    temp = (D*(*ePWM[i]).TBPRD);
    CMPAHRref = modff(temp, &CMPAref);
    (*ePWM[i]).CMPA.all = ((long)CMPAref)<<16 | (long)CMPAHRref<<8;
    }

    for(j=Module;j<8;j++)
    {
    (*ePWM[j]).AQCSFRC.bit.CSFA = 2; // A HIGH
    (*ePWM[j]).AQCSFRC.bit.CSFB = 2; // B HIGH
    }

    while (SFO() == 0) {} // MEP_ScaleFactor calculated by MEP Cal Module

    } //while
    } //main

    void HRPWM_Config(period)
    {
    Uint16 j;

    EALLOW;
    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0; // Disable TBCLK within the EPWM
    EDIS;

    for(j=0; j<MODMAX; j++)
    {
    (*ePWM[j]).TBCTL.bit.PRDLD = TB_SHADOW; // set Shadow load
    (*ePWM[j]).TBPRD = period; // PWM frequency = 1/(2*TBPRD)
    (*ePWM[j]).CMPA.bit.CMPA = period / 2; // set duty 50% initially
    (*ePWM[j]).CMPA.bit.CMPAHR = (1 << 8); // initialize HRPWM extension

    (*ePWM[j]).TBCTR = 0;

    (*ePWM[j]).TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Select up-down count mode

    (*ePWM[j]).TBCTL.bit.HSPCLKDIV = TB_DIV1;
    (*ePWM[j]).TBCTL.bit.CLKDIV = TB_DIV1; // TBCLK = SYSCLKOUT
    (*ePWM[j]).TBCTL.bit.FREE_SOFT = 11;

    (*ePWM[j]).CMPCTL.bit.LOADAMODE = 2; // load on CTR=0 or CTR=PRD
    (*ePWM[j]).CMPCTL.bit.LOADBMODE = 2;
    (*ePWM[j]).CMPCTL.bit.SHDWAMODE = CC_SHADOW;
    (*ePWM[j]).CMPCTL.bit.SHDWBMODE = CC_SHADOW;

    (*ePWM[j]).AQCTLA.bit.CAU = AQ_SET; // PWM toggle high/low
    (*ePWM[j]).AQCTLA.bit.CAD = AQ_CLEAR;
    (*ePWM[j]).AQCTLB.bit.CAD = AQ_SET; // PWM toggle high/low
    (*ePWM[j]).AQCTLB.bit.CAU = AQ_CLEAR;

    EALLOW;
    (*ePWM[j]).HRCNFG.all = 0x0;
    (*ePWM[j]).HRCNFG.bit.EDGMODE = HR_BEP; // MEP control on both edges.
    (*ePWM[j]).HRCNFG.bit.CTLMODE = HR_PHS; // 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_PHS; // 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 updwn count HR control)
    (*ePWM[j]).HRPCTL.bit.HRPE = 1; // Turn on high-resolution period control.
    //################
    (*ePWM[j]).TBPHS.all = 0;
    (*ePWM[j]).TBCTL.bit.SYNCOSEL = TB_SYNC_IN;
    (*ePWM[j]).TBCTL.bit.PHSEN = TB_ENABLE;
    (*ePWM[0]).TBCTL.bit.PHSEN = TB_DISABLE;
    //################
    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;
    (*ePWM[j]).TBCTL.bit.SWFSYNC = 1;
    EDIS;
    }
    }
    ---------------------------------------------------------------------------------------------------------------------------------------------------
    With it's help I've discovered, that the problem with HRPWM occur, when I'm enabling a phase shifting.
    Without a part of code in //### signs, all PWM modules works in HR mod but without phase shifting (of course). When I am enabling phase shifting, HR Mod works only for first PWM modul.
    For D=0.417 Duty Cycle on oscillograph must be 58.3%. I've become 58.301% for first channel and 58.321% for all others (With Phase shifting). I've become DC=58.301% for all channels (Without PHS). With normal ePWM, I've become DC=58.321% for all PWM-channels.

    The big problem is also that TI give no example code for use of TBPHSHR.......
    Thank you, I hope this info will help you to help me))
  • 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

  • Hello Hrishi, thank you for your advice!

    Unfortunately in my case HRCNFG[CTLMODE] makes no effect on PWM... Setting HRCNFG[CTLMODE] to 0x1 was a desperate attempt to change something...
    However I will take in account your advice =)

    Сoncerning second point - no, I use constant frequensy but different duty cycles and phase shifting values.

    Have you some ideas else?)
  • I suporse problems with synchronisation.
    I have programmed regs TBCTL.bit.SWFSYNC and TBCTL.bit.SYNCOSEL as it recommended in datasheet, but for example register EPwmxRegs.EPWMxSYNCOUT.SWEN is absent.... But in datasheet for SWEN is written:

    "This bit enables the TBCTL.SWFSYNC bit to set the
    EPWMxSYNCO signal.
    0 Disabled
    1 The EPWMxSYNCO signal is pulsed for one PWM clock period
    when the TBCTL.SWFSYNC bit is set"
  • 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

  • Hello Hrishi, thank you for the answer! =)

    As you can see in the last code example from me, I use HR registers, as you say.
    Probem is now with TBPHS and namely with syncronisation. You can reed my post up)

    Best regards,
    Anton
  • Hi Anton,

    Apologies for your follow-up reply being dropped. Are you still working through PWM synchronization and still have any related questions?

    If you don't have any more questions, you can press the "This resolved my issue" button on the relevant replies. If you do, please let us know by responding with the details.

    Regards,
    Elizabeth
  • Hallo Elizabeth,

    yes, I still have this problem... T_T
    When I'm working with 8 PWMs and (*ePWM[j]).TBCTL.bit.PHSEN = TB_DISABLE; I've become HRPWM on all 8 channels.[j=0..7]
    But when I turning (*ePWM[j]).TBCTL.bit.PHSEN = TB_ENABLE; [j=1..7] (Disabled for first channel), I've become HRPWM only on first channel and on rest 7 - normaly ePWM...

    Best regards,
    Anton
  • Hi Anton,

    If EPWM1 is to be the master and the other EPWMs are the slaves, then your 2nd configuration (where EPWM1 PHSEN is disabled and others enabled) sounds good.

    Since you're using high-resolution mode and phase shift, look at configuring the EPWM TRREM register. The example Hrishi mentioned in an earlier post shows how to use this register: <path_to_C2000Ware>\device_support\f2837xd\examples\cpu1\hrpwm_deadband_sfo_v8

    Regards,
    Elizabeth
  • Hi Anton,

    I haven't heard from you in more than 2 weeks, so I'm checking in if you were able to resolve this. If not, please reject this resolution and reply to this thread.

    This thread will lock after 60 days of inactivity. If this thread locks and you have remaining questions, please feel free to make a new thread describing the current status of your issue. Thank you for using the TI C2000 E2E forum.

    Regards,
    Elizabeth
  • Hello Elizabeth,
    I tried all the tips, nothing helped)
    But thanks to everyone for help =)
    Best regards,
    Anton