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/TMS320F28035: HRPWM for for hi-res duty control in up-down count (symmetric) mode

Part Number: TMS320F28035
Other Parts Discussed in Thread: CONTROLSUITE, C2000WARE

Tool/software: Code Composer Studio

I am currently trying to implement HRPWM on EPwm1 through EPwm3. However, I am not able to actually get high-resolution duty cycle control. The code compiles fine, but something isn't quite right.

Here is my PWM initialization code:

HRPWM initialization code was duplicated from processors.wiki.ti.com/.../C2000_HRPWM_High_Resolution_Period_and_Duty 

/* Setup Sync*/													\
         EPwm1Regs.TBCTL.bit.SYNCOSEL = 0;       /* Pass through*/			\
         EPwm2Regs.TBCTL.bit.SYNCOSEL = 0;       /* Pass through*/			\
         EPwm3Regs.TBCTL.bit.SYNCOSEL = 0;       /* Pass through*/			\
        																	\
																			\
         /* Allow each timer to be sync'ed*/								\
         EPwm1Regs.TBCTL.bit.PHSEN = 1;										\
         EPwm2Regs.TBCTL.bit.PHSEN = 1;										\
         EPwm3Regs.TBCTL.bit.PHSEN = 1;										\
																			\
         /* Init Timer-Base Period Register for EPWM1-EPWM3*/				\
         EPwm1Regs.TBPRD = v.PeriodMax;										\
         EPwm2Regs.TBPRD = v.PeriodMax;										\
         EPwm3Regs.TBPRD = v.PeriodMax;										\
																			\
         /* Init Timer-Base Phase Register for EPWM1-EPWM3*/				\
         EPwm1Regs.TBPHS.half.TBPHS = 0;									\
         EPwm2Regs.TBPHS.half.TBPHS = 0;									\
         EPwm3Regs.TBPHS.half.TBPHS = 0;									\
																			\
         /* Init Timer-Base Control Register for EPWM1-EPWM3*/				\
         EPwm1Regs.TBCTL.all = PWM_INIT_STATE;								\
         EPwm2Regs.TBCTL.all = PWM_INIT_STATE;								\
         EPwm3Regs.TBCTL.all = PWM_INIT_STATE;								\
																			\
         /* Init Compare Control Register for EPWM1-EPWM3*/					\
         EPwm1Regs.CMPCTL.all = CMPCTL_INIT_STATE;							\
         EPwm2Regs.CMPCTL.all = CMPCTL_INIT_STATE;							\
         EPwm3Regs.CMPCTL.all = CMPCTL_INIT_STATE;							\
																			\
         /* Init Action Qualifier Output A Register for EPWM1-EPWM3*/		\
         EPwm1Regs.AQCTLA.all = AQCTLA_INIT_STATE;							\
         EPwm2Regs.AQCTLA.all = AQCTLA_INIT_STATE;							\
         EPwm3Regs.AQCTLA.all = AQCTLA_INIT_STATE;							\
																			\
         /* Init Dead-Band Generator Control Register for EPWM1-EPWM3*/		\
         EPwm1Regs.DBCTL.all = DBCTL_INIT_STATE;							\
         EPwm2Regs.DBCTL.all = DBCTL_INIT_STATE;							\
         EPwm3Regs.DBCTL.all = DBCTL_INIT_STATE;							\
																			\
         /* Init Dead-Band Generator for EPWM1-EPWM3*/						\
         EPwm1Regs.DBFED = DBCNT_INIT_STATE;								\
         EPwm1Regs.DBRED = DBCNT_INIT_STATE;								\
         EPwm2Regs.DBFED = DBCNT_INIT_STATE;								\
         EPwm2Regs.DBRED = DBCNT_INIT_STATE;								\
         EPwm3Regs.DBFED = DBCNT_INIT_STATE;								\
         EPwm3Regs.DBRED = DBCNT_INIT_STATE;								\
																			\
         /* Init PWM Chopper Control Register for EPWM1-EPWM3*/				\
         EPwm1Regs.PCCTL.all = PCCTL_INIT_STATE;							\
         EPwm2Regs.PCCTL.all = PCCTL_INIT_STATE;							\
         EPwm3Regs.PCCTL.all = PCCTL_INIT_STATE;							\
																			\
         EALLOW;                       /* Enable EALLOW */					\
																			\
         /* Init Trip Zone Select Register*/								\
         EPwm1Regs.TZSEL.all = TZSEL_INIT_STATE;							\
         EPwm2Regs.TZSEL.all = TZSEL_INIT_STATE;							\
         EPwm3Regs.TZSEL.all = TZSEL_INIT_STATE;							\
 																			\
         /* Init Trip Zone Control Register*/								\
         EPwm1Regs.TZCTL.all = TZCTL_INIT_STATE;							\
         EPwm2Regs.TZCTL.all = TZCTL_INIT_STATE;							\
         EPwm3Regs.TZCTL.all = TZCTL_INIT_STATE;							\
																			\
         EDIS;                         /* Disable EALLOW*/

	int16 MPeriod;
	int32 Tmp;
// Now configure the HRPWM resources
    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
    EDIS;

    //Write To CMP, TBPRD, TBPHS registers.
    EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW;             // set Shadow load
    EPwm1Regs.TBPRD = pwm1.PeriodMax;                  // PWM frequency = 1/(2*TBPRD)
    EPwm1Regs.CMPA.half.CMPA = pwm1.PeriodMax / 2;             // set duty 50% initially
    EPwm1Regs.CMPA.half.CMPAHR = (0 << 8);             // initialize HRPWM extension
    EPwm1Regs.TBPHS.all = 0;

    //Configure modes, clock dividers and action qualifier
    EPwm1Regs.TBCTR = 0;
    EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;     // Select up-down count mode
    EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;
    EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;                             // TBCLK = SYSCLKOUT
    EPwm1Regs.TBCTL.bit.FREE_SOFT = 00;

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

    EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;
    EPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR;
    EPwm1Regs.AQCTLB.bit.ZRO = AQ_SET;
    EPwm1Regs.AQCTLB.bit.PRD = AQ_CLEAR;

    EALLOW;

    //Configure HRPWM registers
    EPwm1Regs.HRCNFG.all = 0x0;
    EPwm1Regs.HRCNFG.bit.EDGMODE = HR_BEP;                      // MEP control on both edges
    EPwm1Regs.HRCNFG.bit.CTLMODE = HR_CMP;                      // CMPAHR and TBPRDHR HR control
    EPwm1Regs.HRCNFG.bit.HRLOAD  = HR_CTR_ZERO_PRD;    // load on CTR = 0 and CTR = TBPRD
    EPwm1Regs.HRCNFG.bit.AUTOCONV = 1;                               // Enable autoconversion
    EPwm1Regs.HRPCTL.bit.HRPE = 1;                                         // Turn on high-resolution period control

    //set TBCTL[PHSEN] = 1
    EPwm1Regs.TBCTL.bit.PHSEN = 1;

    //set HRPCTL[TBPHSHRLOADE] = 1
    EPwm1Regs.HRPCTL.bit.TBPHSHRLOADE = 1;
    EDIS;

    //Write To CMP, TBPRD, TBPHS registers.
    EPwm2Regs.TBCTL.bit.PRDLD = TB_SHADOW;             // set Shadow load
    EPwm2Regs.TBPRD = pwm1.PeriodMax;                          // PWM frequency = 1/(2*TBPRD)
    EPwm2Regs.CMPA.half.CMPA = pwm1.PeriodMax / 2;             // set duty 50% initially
    EPwm2Regs.CMPA.half.CMPAHR = (0 << 8);             // initialize HRPWM extension
    EPwm2Regs.TBPHS.all = 0;

    //Configure modes, clock dividers and action qualifier
    EPwm2Regs.TBCTR = 0;
    EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;     // Select up-down count mode
    EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;
    EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;
    EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV1;                             // TBCLK = SYSCLKOUT
    EPwm2Regs.TBCTL.bit.FREE_SOFT = 00;

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

    EPwm2Regs.AQCTLA.bit.CAU = AQ_SET;
    EPwm2Regs.AQCTLA.bit.CAD = AQ_CLEAR;
    EPwm2Regs.AQCTLB.bit.ZRO = AQ_SET;
    EPwm2Regs.AQCTLB.bit.PRD = AQ_CLEAR;

    EALLOW;

    //Configure HRPWM registers
    EPwm2Regs.HRCNFG.all = 0x0;
    EPwm2Regs.HRCNFG.bit.EDGMODE = HR_BEP;                      // MEP control on both edges
    EPwm2Regs.HRCNFG.bit.CTLMODE = HR_CMP;                      // CMPAHR and TBPRDHR HR control
    EPwm2Regs.HRCNFG.bit.HRLOAD  = HR_CTR_ZERO_PRD;    // load on CTR = 0 and CTR = TBPRD
    EPwm2Regs.HRCNFG.bit.AUTOCONV = 1;                               // Enable autoconversion
    EPwm2Regs.HRPCTL.bit.HRPE = 1;                                         // Turn on high-resolution period control

    //set TBCTL[PHSEN] = 1
    EPwm2Regs.TBCTL.bit.PHSEN = 1;

    //set HRPCTL[TBPHSHRLOADE] = 1
    EPwm2Regs.HRPCTL.bit.TBPHSHRLOADE = 1;

    EDIS;

    //Write To CMP, TBPRD, TBPHS registers.
    EPwm3Regs.TBCTL.bit.PRDLD = TB_SHADOW;             // set Shadow load
    EPwm3Regs.TBPRD = pwm1.PeriodMax;                          // PWM frequency = 1/(2*TBPRD)
    EPwm3Regs.CMPA.half.CMPA = pwm1.PeriodMax / 2;             // set duty 50% initially
    EPwm3Regs.CMPA.half.CMPAHR = (0 << 8);             // initialize HRPWM extension
    EPwm3Regs.TBPHS.all = 0;

    //Configure modes, clock dividers and action qualifier
    EPwm3Regs.TBCTR = 0;
    EPwm3Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;     // Select up-down count mode
    EPwm3Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;
    EPwm3Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;
    EPwm3Regs.TBCTL.bit.CLKDIV = TB_DIV1;                             // TBCLK = SYSCLKOUT
    EPwm3Regs.TBCTL.bit.FREE_SOFT = 00;

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

    EPwm3Regs.AQCTLA.bit.CAU = AQ_SET;
    EPwm3Regs.AQCTLA.bit.CAD = AQ_CLEAR;
    EPwm3Regs.AQCTLB.bit.ZRO = AQ_SET;
    EPwm3Regs.AQCTLB.bit.PRD = AQ_CLEAR;

    EALLOW;

    //Configure HRPWM registers
    EPwm3Regs.HRCNFG.all = 0x0;
    EPwm3Regs.HRCNFG.bit.EDGMODE = HR_BEP;                      // MEP control on both edges
    EPwm3Regs.HRCNFG.bit.CTLMODE = HR_CMP;                      // CMPAHR and TBPRDHR HR control
    EPwm3Regs.HRCNFG.bit.HRLOAD  = HR_CTR_ZERO_PRD;    // load on CTR = 0 and CTR = TBPRD
    EPwm3Regs.HRCNFG.bit.AUTOCONV = 1;                               // Enable autoconversion
    EPwm3Regs.HRPCTL.bit.HRPE = 1;                                         // Turn on high-resolution period control

    //set TBCTL[PHSEN] = 1
    EPwm3Regs.TBCTL.bit.PHSEN = 1;

    //set HRPCTL[TBPHSHRLOADE] = 1
    EPwm3Regs.HRPCTL.bit.TBPHSHRLOADE = 1;

    //Enable TBCLKSYNC
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;

    //Perform a software sync
    EPwm1Regs.TBCTL.bit.SWFSYNC = 1;
    EPwm2Regs.TBCTL.bit.SWFSYNC = 1;
    EPwm3Regs.TBCTL.bit.SWFSYNC = 1;

    EDIS;

Thank you!

-Peter

  • Hi Peter,

    Please make sure that the HRPWM peripheral clock is enabled. PCLKCR0[HRPWMENCLK] .

    Hrishi
  • I've now set the EPWM1ENCLK and HRPWMENCLK as shown below. However, I still don't seem to be getting High Resolution duty cycle control.

        SysCtrlRegs.PCLKCR1.bit.EPWM1ENCLK = 1;
        SysCtrlRegs.PCLKCR0.bit.HRPWMENCLK = 1;
    
        //Enable TBCLKSYNC
        SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
    
        //Perform a software sync
        EPwm1Regs.TBCTL.bit.SWFSYNC = 1;
        EPwm2Regs.TBCTL.bit.SWFSYNC = 1;
        EPwm3Regs.TBCTL.bit.SWFSYNC = 1;

    In my project, I call the PWM_INIT_MACRO() function (from f2803xpwm_PM.h) first,  to set up the regular 3 phase PWM. Is there anything in this that needs to be modified to get HRPWM to work properly?

    Thank You!

  • Hello,

    It appears you are using the HRPWM with HRCNFG[EDGMODE] = HR_BEP. As far as I can tell this is not going to do what you expect because the HRPWM can only delay edges. Therefore both the rising and falling edges of you pulse will be delayed by the same amount and the pulse width will remain unchanged.

    Kind regards,

    Pierre

  • Pierre,

    In up-down count mode HRPWM should be configured for hi-res edge positioning for both edges to be able to achieve high resolution duty control that is symmetric about the mid-point of the switching period. Peter has this part right.

    Peter,

    Please make sure that the EPWM1ENCLK and HRPWMENCLK instructions are executed before any of the PWM registers are written to. If you write to the control registers without the corresponding clock enabled, the register writes will not go through.

    I also noticed that you have TBCTL[PHSEN] = 1 for PWM1. Is that intentional i.e. do you want PWM1 time-base to be synced to an external event/signal? If that is the case you might see issues at the PWM outputs depending on the relationship between the period of the external event and the programmed PWM period (TBPRD). You can make PWM1 the master time-base by setting PHSEN = 0.

    I hope this helps.
    Hrishi
  • Hrishi,

    See attached oscilloscope captures of the behaviour of the HRPWM in up-down count mode with positioning on both edges. I still think you are wrong.

    I just ran the attached CCS project on a F28035 controlCard.

    EPWM1A (GPIO0) is the red signal (it has HRPWM).

    EPWM1B (GPIO1) is the blue signal (no HRPWM).

    Here is the result with FEP mode:

    Then the result in REP mode :

    And finally in BEP mode:

    These pictures make it pretty clear the HRPWM only delays the edges.

    You claim that the HRPWM can perform high-resolution duty control that is symmetric about the mid-point of the switching period. If it is truly the case then surely you will be able to provide an example CCS project which demonstrates this.HRPWM_UPDOWN_DUTY.zip

  • Pierre,

    I looked through your code. Please change HRCNFG[HRLOAD] from 0 to 2 (load on CTR = 0 or PRD). 

    This should solve your problem.

    Hrishi

  • Hrishi,

    I tried your suggestion and set HRCNFG[HRLOAD]=2. It doesn't change anything.

    Have you actually tested this or is it theoretical?

  • Pierre,

    This has been used in production for over a decade by many customers. It works.

    It is a matter of making sure the configuration is correct in your code. Are you also using load on zero and period for CMPCTL(LOADAMODE)? If not, please do so. Also, are you taking care of the EALOW registers?

    I am not at work right now and cannot look at the your code again till later. Let me know how this goes and if this doesn't work, we will try to debug your code on our setup.

    Hrishi

  • Hrishi,

    I want to believe you. But I can't get it to work the way you describe. I did another test setting CMPCTL[LODAMODE]=2 and that doesn't solve anything.

    If this has been used in production then why is there no mention of it in the datasheet? Why are there no example projects in the ControlSuite?

    Here is what the SPRUGE8E document states:

    As far as I can tell it is implied that MEP control of both edges can only be used for period control.

    I would be very glad if you could run my code on your setup. It is a self-contained project with all my code in a single source file. The main function is about 30 lines of code so it should be very easy to analyze the configuration. 

    Pierre

  • Pierre,

    I see what the problem is. You are using CMPA:CMPAHR for HR output on PWM1A and are using CMPA for non-HR output on PWM1B. In this case what you are seeing is exactly what is expected.

    Please use CMPB for PWM1B generation. Keep CMPB value the same as CMPA value and then look at PWM1A edges with respect to PWM1B edges. You will see that HRPWM on PWM1A is symmetric about PRD. Also change the CMPCTL(LOADAMODE) back to load on PRD.

    Hrishi
  • Hrishi,

    I came to the same conclusion. I was using ControlSuite version 126 but I noticed that a new example project was introduced in version 127.

    From what I understand there is a kind of "hidden" mechanism which allows the HRPWM to move the rising edge backwards by altering the effective value of CMPA?

    I did the following test:

    • EPWM1A (pink) has HRPWM and CMPAHR set to 1/3 TBCLK
    • EPWM1B (blue) uses the same CMPA but no HR
    • EPWM2A (green) has the same value in its own CMPA but no HR

    Here is the result with annotations explaining how I understand it:

    Can you confirm that this is more or less what's happening under the hood?

    Furthermore do you think it would be possible to improve the documentation in the future so that it is explained more clearly? I haven't seen anything about this mechanism in any datasheet or reference manual, even though I have read the documents for F28035 / F28075 / F28379 many times.

    Regards,

    Pierre

  • Pierre,

    I am glad this is sorted out. Thank you for checking this out quickly. Yes, I can confirm it is more or less the same way as you have described.

    Documenting this part gets a bit tricky. We have added a few examples over the years. In fact we have an example in C2000Ware that implements HRPRD (hi-res period), HRDUTY (duty), HRPHS (phase shift) and HRDB (dead-band) simultaneously. In any case I will forward your feedback to others on the team who are responsible for maintaining this documentation.

    Hrishi

  • Hrishi,

    I made the changes you suggested. However, I am still not seeing High Resolution control..

    // Initialize PWM module pwm1.PeriodMax = SYSTEM_FREQUENCY*1000000*T/2; // Prescaler X1 (T1), ISR period = T x 1 EALLOW; SysCtrlRegs.PCLKCR1.bit.EPWM1ENCLK = 1; SysCtrlRegs.PCLKCR0.bit.HRPWMENCLK = 1; EDIS; PWM_INIT_MACRO(pwm1) // Now configure the HRPWM resources EALLOW; SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; EDIS; //Write To CMP, TBPRD, TBPHS registers. EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW; // set Shadow load EPwm1Regs.TBPRD = pwm1.PeriodMax; // PWM frequency = 1/(2*TBPRD) EPwm1Regs.CMPA.half.CMPA = pwm1.PeriodMax / 2; // set duty 50% initially EPwm1Regs.CMPA.half.CMPAHR = (0 << 8); // initialize HRPWM extension EPwm1Regs.TBPHS.all = 0; //Configure modes, clock dividers and action qualifier EPwm1Regs.TBCTR = 0; EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Select up-down count mode EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE; EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1; // TBCLK = SYSCLKOUT EPwm1Regs.TBCTL.bit.FREE_SOFT = 00; EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // LOAD CMPA on CTR = 0 EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm1Regs.AQCTLA.bit.CAU = AQ_SET; EPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR; EPwm1Regs.AQCTLB.bit.ZRO = AQ_SET; EPwm1Regs.AQCTLB.bit.PRD = AQ_CLEAR; EALLOW; //Configure HRPWM registers EPwm1Regs.HRCNFG.all = 0x0; EPwm1Regs.HRCNFG.bit.EDGMODE = HR_BEP; // MEP control on both edges EPwm1Regs.HRCNFG.bit.CTLMODE = HR_CMP; // CMPAHR and TBPRDHR HR control EPwm1Regs.HRCNFG.bit.HRLOAD = HR_CTR_ZERO_PRD; // load on CTR = 0 and CTR = TBPRD EPwm1Regs.HRCNFG.bit.AUTOCONV = 1; // Enable autoconversion EPwm1Regs.HRPCTL.bit.HRPE = 1; // Turn on high-resolution period control //set TBCTL[PHSEN] = 1 EPwm1Regs.TBCTL.bit.PHSEN = 0; //set HRPCTL[TBPHSHRLOADE] = 1 EPwm1Regs.HRPCTL.bit.TBPHSHRLOADE = 1; EDIS; //Write To CMP, TBPRD, TBPHS registers. EPwm2Regs.TBCTL.bit.PRDLD = TB_SHADOW; // set Shadow load EPwm2Regs.TBPRD = pwm1.PeriodMax; // PWM frequency = 1/(2*TBPRD) EPwm2Regs.CMPA.half.CMPA = pwm1.PeriodMax / 2; // set duty 50% initially EPwm2Regs.CMPA.half.CMPAHR = (0 << 8); // initialize HRPWM extension EPwm2Regs.TBPHS.all = 0; //Configure modes, clock dividers and action qualifier EPwm2Regs.TBCTR = 0; EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Select up-down count mode EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE; EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV1; // TBCLK = SYSCLKOUT EPwm2Regs.TBCTL.bit.FREE_SOFT = 00; EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // LOAD CMPA on CTR = 0 EPwm2Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm2Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm2Regs.AQCTLA.bit.CAU = AQ_SET; EPwm2Regs.AQCTLA.bit.CAD = AQ_CLEAR; EPwm2Regs.AQCTLB.bit.ZRO = AQ_SET; EPwm2Regs.AQCTLB.bit.PRD = AQ_CLEAR; EALLOW; //Configure HRPWM registers EPwm2Regs.HRCNFG.all = 0x0; EPwm2Regs.HRCNFG.bit.EDGMODE = HR_BEP; // MEP control on both edges EPwm2Regs.HRCNFG.bit.CTLMODE = HR_CMP; // CMPAHR and TBPRDHR HR control EPwm2Regs.HRCNFG.bit.HRLOAD = HR_CTR_ZERO_PRD; // load on CTR = 0 and CTR = TBPRD EPwm2Regs.HRCNFG.bit.AUTOCONV = 1; // Enable autoconversion EPwm2Regs.HRPCTL.bit.HRPE = 1; // Turn on high-resolution period control //set TBCTL[PHSEN] = 1 EPwm2Regs.TBCTL.bit.PHSEN = 1; //set HRPCTL[TBPHSHRLOADE] = 1 EPwm2Regs.HRPCTL.bit.TBPHSHRLOADE = 1; EDIS; //Write To CMP, TBPRD, TBPHS registers. EPwm3Regs.TBCTL.bit.PRDLD = TB_SHADOW; // set Shadow load EPwm3Regs.TBPRD = pwm1.PeriodMax; // PWM frequency = 1/(2*TBPRD) EPwm3Regs.CMPA.half.CMPA = pwm1.PeriodMax / 2; // set duty 50% initially EPwm3Regs.CMPA.half.CMPAHR = (0 << 8); // initialize HRPWM extension EPwm3Regs.TBPHS.all = 0; //Configure modes, clock dividers and action qualifier EPwm3Regs.TBCTR = 0; EPwm3Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Select up-down count mode EPwm3Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE; EPwm3Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; EPwm3Regs.TBCTL.bit.CLKDIV = TB_DIV1; // TBCLK = SYSCLKOUT EPwm3Regs.TBCTL.bit.FREE_SOFT = 00; EPwm3Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // LOAD CMPA on CTR = 0 EPwm3Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; EPwm3Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm3Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm3Regs.AQCTLA.bit.CAU = AQ_SET; EPwm3Regs.AQCTLA.bit.CAD = AQ_CLEAR; EPwm3Regs.AQCTLB.bit.ZRO = AQ_SET; EPwm3Regs.AQCTLB.bit.PRD = AQ_CLEAR; EALLOW; //Configure HRPWM registers EPwm3Regs.HRCNFG.all = 0x0; EPwm3Regs.HRCNFG.bit.EDGMODE = HR_BEP; // MEP control on both edges EPwm3Regs.HRCNFG.bit.CTLMODE = HR_CMP; // CMPAHR and TBPRDHR HR control EPwm3Regs.HRCNFG.bit.HRLOAD = HR_CTR_ZERO_PRD; // load on CTR = 0 and CTR = TBPRD EPwm3Regs.HRCNFG.bit.AUTOCONV = 1; // Enable autoconversion EPwm3Regs.HRPCTL.bit.HRPE = 1; // Turn on high-resolution period control //set TBCTL[PHSEN] = 1 EPwm3Regs.TBCTL.bit.PHSEN = 1; //set HRPCTL[TBPHSHRLOADE] = 1 EPwm3Regs.HRPCTL.bit.TBPHSHRLOADE = 1; //Enable TBCLKSYNC SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; //Perform a software sync EPwm1Regs.TBCTL.bit.SWFSYNC = 1; EPwm2Regs.TBCTL.bit.SWFSYNC = 1; EPwm3Regs.TBCTL.bit.SWFSYNC = 1; EDIS;

  • Sorry, I put my comment in the wrong spot.. I made the changes you suggested but I am still not getting high resolution PWM...
  • If you have an example project that can output three high-resolutions PWM signals, you can just share that.
  • Hi Peter,

    Please set both HRPCTL[HRPE] and HRPCTL[TBPHSHRLOADE] to 0 for all PWMs. I do not see anything else wrong with your configuration.

    How are you verifying presence or absence of high resolution? Can you share some oscilloscope captures? Are all PWM outputs behaving the same way? Can you please do something similar to what I suggested Pierre above - use CMPB to generate PWM1B output without high resolution and compare this with PWM1A output with high resolution? Trigger the oscilloscope on PWM1B edge. You can make dead-band RED/FED values = 0 for this test, just to simplify debug. You can add this back in later.

    Thank you.
    Hrishi
  • Hi Peter,

    I copied you code into my CCS project and the HRPWM seems to be working fine. Maybe the issue is with code unrelated to the HRPWM such as the TZ or the PWM Chopper?

    If you'd like you can attach your CCS project and I'll see if it runs ok on my controlCard.

    Regards,

    Pierre

  • I made the changes you suggested, I guess there could be something wrong with how I'm setting the duty cycle registers. The code below is what I'm using to do this, which I copied from an example file for a different controlcard. Below is the output of the high-side PWM channels for PWM1 and PWM 2 where I slowly increased Va_cmd. I am still seeing a resolution limit of a little under 20 ns.

        CMPA_reg_val_1 = ((long)Va_cmd * EPwm1Regs.TBPRD)>>15;
        CMPB_reg_val_1 = ((long)Va_cmd * EPwm1Regs.TBPRD)>>15;
        temp = ((long)Va_cmd * EPwm1Regs.TBPRD);
        temp = temp - ((long)CMPA_reg_val_1<<15);
        CMPAHR_reg_val_1 = temp<<1; // convert to Q16

        CMPA_reg_val_2 = ((long)Vb_cmd * EPwm2Regs.TBPRD)>>15;
        CMPB_reg_val_2 = ((long)Vb_cmd * EPwm2Regs.TBPRD)>>15;
        temp = ((long)Vb_cmd * EPwm2Regs.TBPRD);
        temp = temp - ((long)CMPA_reg_val_2<<15);
        CMPAHR_reg_val_2 = temp<<1; // convert to Q16
    
        CMPA_reg_val_3 = ((long)Vc_cmd * EPwm3Regs.TBPRD)>>15;
        CMPB_reg_val_3 = ((long)Vc_cmd * EPwm3Regs.TBPRD)>>15;
        temp = ((long)Vc_cmd * EPwm3Regs.TBPRD);
        temp = temp - ((long)CMPA_reg_val_3<<15);
        CMPAHR_reg_val_3 = temp<<1; // convert to Q16
    
        EPwm1Regs.CMPA.all = ((long)CMPA_reg_val_1)<<16 | CMPAHR_reg_val_1; // loses lower 8-bits
        EPwm1Regs.CMPB = (long)CMPB_reg_val_1<<16; // loses lower 8-bits
        EPwm2Regs.CMPA.all = ((long)CMPA_reg_val_2)<<16 | CMPAHR_reg_val_2; // loses lower 8-bits
        EPwm2Regs.CMPB = (long)CMPB_reg_val_2<<16; // loses lower 8-bits
        EPwm3Regs.CMPA.all = ((long)CMPA_reg_val_3)<<16 | CMPAHR_reg_val_3; // loses lower 8-bits
        EPwm3Regs.CMPB = (long)CMPB_reg_val_3<<16; // loses lower 8-bits

    1373.PM_Sensorless_mod.zip

  • Hi Peter,

    Sorry for the delay in responding. Are you still facing this issue? If yes, here's what you can do. You can debug your code by looking at the CMPAHR value directly in the expressions window in CCS. You can also write to the CMPAHR register directly from the expressions window in CCS. 

    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, for example, calculate 0.2*(0xFF00) = 0x3300. This value should then be written to CMPAHR register.

    Let me know what you find with this. I hope this helps.

    Thanks.

    Hrishi

  • Hi Peter,

    I am going to mark this post as 'resolved' for now. Feel free to reject the resolution if you want to reopen it.

    Hrishi
  • Hrishi,

    I have a follow-up question on this topic. I posted it here. Could you please take a look at it and tell me what you think?

    Kind Regards,

    Pierre

  • Hi Pierre,

    I have responded to that other post.

    Hrishi