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.

f28035 epwm interrupt on ZERO or CMP?



Hello,

I am running a epwm1 A at high frequency and epwm2 A at low frequency. I am wanting to set the epwm1 duty cycle at the start of epwm2 (ZERO) and again on epwm2 end duty cycle (CMP). In other words epwm2 start of period sets epwm1 duty cycle. Then epwm2 end of duty cycle sets epwm1 duty cycle.

I do not see a interrupt select mode for this configuration. Is it possible? Can I alternatively just use GPIO rising/falling edge interrupt for this?

Thanks,

Dave

  • Dave,

    Unfortunately you can't do both together.  The INTSEL field in the ETSEL register for ePWM2 will allow you to select one trigger source or the other, but not both.

    What you can to is change the INTSEL bits from within the ISR, so the zero match ISR writes 100 (assuming it's up-counting), and the compare match ISR writes 001.  You can check the I/O pin in the ISR by reading the GPADAT register to determine which event triggered the interrupt.

    Regards,

    Richard

  • Hi Richard,

    Thank you for the response. When you say the ISR writes xxx, what register are you referring to?

    Thank you,
    Dave
  • Richard,

    I believe I understand now. You are discussing writing the compare mode. Not reading a status register. I will work on implementation.

    Thank you.
  • Hi Dave,

    FYI: another option which can give a more generic solution, is to use a 'downstream' PWM.  Have it be synchronized to ePWM2. 

    The downstream PWM can be the same period as the upstream one, but it doesn't have to.  This means that you can make it such that multiple ISRs happen per PWM2 period.

    The downstream PWM also doesn't have to be in synch to PWM2 (ie it can have a phase offset via TBPHS).  This can also be useful in some circumstances.


    Thank you,
    Brett

  • Hi Brett,

    Please see my code snippet below. PWM2 is running at 15 Hz. PWM1 (Piezo_PWM ) is 6.25 KHz (no interrupt). When running I only see epwm2_isr_cnt and epwm_low_cnt incrementing. However if I place a breakpoint on the "epqm2_GPIO_state = " assignment line and step through, epqm2_GPIO_state is always 1 as expected. Why does this not work at run time? I also tried loading into FLASH with same results. I am running a Piccolo F28035 control card in docking board.

    //////////////////// PWM2 interrupt code
    Uint32 epwm_high_cnt = 0;
    Uint32 epwm_low_cnt = 0;
    Uint32 epwm2_isr_cnt = 0;
    volatile Uint16 epqm2_GPIO_state;
    __interrupt void epwm2_isr(void)
    {
    // Update the CMPA and CMPB values
    epwm2_isr_cnt++;
    epqm2_GPIO_state = GpioDataRegs.GPADAT.bit.GPIO2; // Get ePWM output pin state
    epqm2_GPIO_state = GpioDataRegs.GPADAT.bit.GPIO2; // Get ePWM output pin state
    if(epqm2_GPIO_state == 1)
    {
    epwm_high_cnt++;
    Piezo_PWM = EPWM1_TIMER_TBPRD / 2; // Set DAC PWM to full on
    // EPwm2Regs.ETSEL.bit.INTSEL = ET_CTRD_CMPA; // Select INT on Zero event
    }
    else
    {
    epwm_low_cnt++;
    Piezo_PWM = 0; // Set DAC PWM to full on
    // EPwm2Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event
    }
    // Clear INT flag for this timer
    EPwm2Regs.ETCLR.bit.INT = 1;
    EPwm1Regs.ETSEL.bit.INTEN = 1; // Enable INT
    // Acknowledge this interrupt to receive more interrupts from group 3
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
    }


    ///////////////////// PWM2 init code
    void InitEPwm2Example()
    {
    // Setup TBCLK
    EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up
    EPwm2Regs.TBPRD = EPWM2_TIMER_TBPRD; // Set timer period
    EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
    EPwm2Regs.TBPHS.half.TBPHS = 0x0000; // Phase is 0
    EPwm2Regs.TBCTR = 0x0000; // Clear counter
    EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV32; // Clock ratio to SYSCLKOUT
    EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV32;

    // Setup shadow register load on ZERO
    EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
    EPwm2Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
    EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
    EPwm2Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;

    // Set Compare values
    EPwm2Regs.CMPA.half.CMPA = EPWM2_MIN_CMPA; // Set compare A value
    EPwm2Regs.CMPB = EPWM2_MAX_CMPB; // Set Compare B value

    // Set actions
    EPwm2Regs.AQCTLA.bit.ZRO = AQ_SET; // Clear PWM2A on Period
    EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Set PWM2A on event A, up count

    EPwm2Regs.AQCTLB.bit.ZRO = AQ_SET; // Clear PWM2B on Period
    EPwm2Regs.AQCTLB.bit.CBU = AQ_CLEAR; // Set PWM2B on event B, up count

    // Interrupt where we will change the Compare Values
    // EPwm2Regs.ETSEL.bit.INTSEL = (ET_CTR_ZERO | ET_CTRU_CMPA); // Select INT on Zero event
    EPwm2Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event
    EPwm2Regs.ETSEL.bit.INTEN = 1; // Enable INT
    EPwm2Regs.ETPS.bit.INTPRD = ET_1ST; // Generate INT on every event

    // Information this example uses to keep track
    // of the direction the CMPA/CMPB values are
    // moving, the min and max allowed values and
    // a pointer to the correct ePWM registers
    epwm2_info.EPwm_CMPA_Direction = EPWM_CMP_UP; // Start by increasing CMPA
    epwm2_info.EPwm_CMPB_Direction = EPWM_CMP_UP; // and decreasing CMPB
    epwm2_info.EPwmTimerIntCount = 0; // Zero the interrupt counter
    epwm2_info.EPwmRegHandle = &EPwm2Regs; // Set the pointer to the ePWM module
    epwm2_info.EPwmMaxCMPA = EPWM2_MAX_CMPA; // Setup min/max CMPA/CMPB values
    epwm2_info.EPwmMinCMPA = EPWM2_MIN_CMPA;
    epwm2_info.EPwmMaxCMPB = EPWM2_MAX_CMPB;
    epwm2_info.EPwmMinCMPB = EPWM2_MIN_CMPB;
    }

    Pleas advise.

    Thanks,
    Dave
  • Hi Dave,

    Two thoughts:

    Are you outputting PWM2 to a pin so that you can measure the PWM with an oscilloscope.  Is it doing what you expect?

    Based on your comments, I am assuming the PWM's CMPA is greater than around 20?


    Thank you,
    Brett