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.

TMS320F28375D: 0% and 100% duty cycle ePWM workaround

Part Number: TMS320F28375D

Section 15.6.5 of SPRUHM8I suggests keeping the CMPR values within a range of 1 to TBPRD-1 to ensure proper PWM operation.  It then references an old (2006) appnote SPRAAI1 that has a work-around for achieving 0% and 100% duty cycle.  After some searching on this forum I've found several incomplete answers as to whether this is actually necessary on newer devices that have a Type 4 ePWM module.  The most complete answer I've found is here:

https://e2e.ti.com/support/microcontrollers/c2000/f/171/t/646249

The linked thread seems to indicate that CMPx = 0 should work fine but there may be an issue transitioning from CMPx = 0 to CMPx != 0.  The thread kind of dies after that.  Does this mean we don't have to do anything special transitioning to CMPx = 0 but the workaround still applies transitioning back to a non-zero value?  What about CMPx = TBPRD?  

My configuration

- Up/Down count mode

- shadow load CMPx registers on ZRO and TBPRD

- There is an ISR on both ZRO and TBPRD events so I am loading the CMPx registers twice per PWM period

- Action qualifier is configured to set on up count and clear on down count

Assuming this work-around is necessary, and since I'm loading CMPx registers on both ZRO and TBPRD, would I need to implement the work-around for both CMPx = 0 and CMPx = TBPRD?

  • I dont think CMPx=TBPRD would cause any problem. The workaround being only implemented on CMPx=0 should fix your issue. Overall you can definitley have 0% and 100% duty cycle if you are not using high resolution (HRPWM) submodule inside ePWM.

    Nima

  • The way I'm interpreting the Up-Down Count Mode example in the work-around appnote SPRAA1 is that ISR and shadow loading of compare registers is happening on TBCNT = ZRO.  Since shadow loading happens on ZRO in this example it makes sense that they are only handling CMPx = 0 as a special case.  I would then assume that if someone was shadow loading at TBCNT =TBPRD they would have to handle CMPx = TBPRD as a special case.  Agreed?  

    In my case I am shadow loading on both ZRO and TBPRD events and I have an ISR on both events.  I am updating CMPx twice per PWM cycle.  So, extending my thought process from the previous paragraph, if this is still a problem with Type 4 ePWM modules then I'd have to handle both CMPx = ZRO and CMPx = TBPRD.  Agreed?

  • I agree with both items. In general you are try to achieve both 0% duty and 100% duty, when I last wrote my ePWM code that had that requirement I didnt have an issue. I'm looking to  see if I can find my old Type4 PWM code.

  • I was able to get 0% to 100% duty with the code below:

    void init(){    
        EPWM_setTimeBasePeriod(epwm_base, EPWM_TBPRD - 1);
        EPWM_setPhaseShift(epwm_base, 0U);
        EPWM_setTimeBaseCounter(epwm_base, 0U);
        EPWM_setEmulationMode(epwm_base, EPWM_EMULATION_FREE_RUN);
    
        EPWM_setCounterCompareValue(epwm_base,
                                    EPWM_COUNTER_COMPARE_A,
                                    0);
        EPWM_setCounterCompareValue(epwm_base,
                                    EPWM_COUNTER_COMPARE_B,
                                    0);
    
        EPWM_setTimeBaseCounterMode(epwm_base, EPWM_COUNTER_MODE_UP);
        EPWM_disablePhaseShiftLoad(epwm_base);
        EPWM_setClockPrescaler(epwm_base,
                               EPWM_CLOCK_DIVIDER_1,
                               EPWM_HSCLOCK_DIVIDER_1);
    
        EPWM_setCounterCompareShadowLoadMode(epwm_base,
                                             EPWM_COUNTER_COMPARE_A,
                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);
        EPWM_setCounterCompareShadowLoadMode(epwm_base,
                                             EPWM_COUNTER_COMPARE_B,
                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);
    
    
        EPWM_setActionQualifierAction(epwm_base,
                                      EPWM_AQ_OUTPUT_B,
                                      EPWM_AQ_OUTPUT_HIGH,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    
        EPWM_setActionQualifierAction(epwm_base,
                                      EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_HIGH,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    
        EPWM_setActionQualifierAction(epwm_base,
                                      EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_LOW,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
        EPWM_setActionQualifierAction(epwm_base,
                                      EPWM_AQ_OUTPUT_B,
                                      EPWM_AQ_OUTPUT_LOW,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
    
    }
    void booster_epwm_setDuty(uint32_t epwm_base, EPWM_CounterCompareModule cmp_module, uint32_t duty)
    {
        uint16_t result = (uint16_t)(((duty *(EPWM_TBPRD)))/100);
        EPWM_setCounterCompareValue(epwm_base,
                                    cmp_module,
                                    result);
    }