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.

How to change ISR interrupt frequency?

Other Parts Discussed in Thread: CONTROLSUITE

Hi,

I am using an F28027 Launchpad and am not quite sure how to change the ISR interrupt frequency. Since the interrupt is enabled by epwm in my case, I guess the adjustion of frequency lies in the following few lines of codes.

// Reassign ISRs.

EALLOW;

// This is needed to write to EALLOW protected registers

PieVectTable.EPWM1_INT = &MainISR;

EDIS;

// Enable PIE group 3 interrupt 1 for EPWM1_INT

    PieCtrlRegs.PIEIER3.bit.INTx1 = 1;

 

// Enable CNT_zero interrupt using EPWM1 Time-base

    EPwm1Regs.ETSEL.bit.INTEN = 1;  

// Enable EPWM1INT generation

    EPwm1Regs.ETSEL.bit.INTSEL = 1; 

// Enable interrupt CNT_zero event

    EPwm1Regs.ETPS.bit.INTPRD = 1;  

// Generate interrupt on the 1st event

EPwm1Regs.ETCLR.bit.INT = 1;    


// Enable CPU INT3 for EPWM1_INT:

IER |= M_INT3;

 

// Enable global Interrupts and higher priority real-time debug events:

EINT;  

// Enable Global interrupt INTM

ERTM;

// Enable Global realtime interrupt DBGM

// IDLE loop. Just sit and loop forever:

for(;;);  //infinite loop

 

I can't find out where I can change the interrput frequency. Please help.

 

Thanks

Jingzhe

  • Hi Jingzhe!

    Maybe you mean PWM period versus Frequency?

    Regards,

    Igor

  • Jingzhe,

    The ePWM1 interrupt frequency is controlled by the ePWM1 period.  Find where the code is setting the EPwm1Regs.TBPRD register.  That value controls the period.

    Regards,

    David

     

  • Hi David,

    I can see that PeriodMax  is then defined by        pwm.PeriodMax = SYSTEM_FREQUENCY*1000000*T/2.

    SYSTEM_FREQUENCY in my case is 100MHz and T is determined by ISR_FREQUENCY = 10kHz.

    However, I observed that the ISR interrupt frequency does not act as 10kHz but like a 6kHz.

    My device is F28027. Is the SYSTEM_FREQUENCY wrong in my case?

    Jingzhe

  • Jingzhe,

    The F28027 is a 60 MHz device.  You should confirm the PLL setting and source clock in your code.  Since you are expecting 10 kHz PWM, and are seeing 6 kHz, the 60 MHz would seem to make sense.

    Jingzhe Wu said:

    I can see that PeriodMax  is then defined by        pwm.PeriodMax = SYSTEM_FREQUENCY*1000000*T/2.

    SYSTEM_FREQUENCY in my case is 100MHz and T is determined by ISR_FREQUENCY = 10kHz.

    I do not follow the equation you show.  For symmetric PWM (edge centered, timer in up/down-count mode), you have:

       fpwm = fsystem/(2*TxPRD)   where TxPRD is the timer period register value.

    For example, if you have fsystem=60 MHz, and set TxPRD = 500, you get fpwm=60 kHz.

    For asymmetric PWM (edge justified, timer in up-count mode) you have:

       fpwm = fsystem/(txPRD + 1)

    So, if you have fsystem=60 MHz, and set TxPRD=999, you get fpwm=60 kHz.

    Regards,

    David

     

     

  • Hi David.

    It indeed makes sense.

    But if I look at the problem at a different angle. According to the ePWM document SPRUGE5, in the section of Time Base submodule, the document describes that the trigger of epwm is made by counting from zero to TBPRD at the rate of SYSCLKOUT. In my case a factor of 1/2 is given to scale CPU clock.

    My device is F28027, therefore presumably the CPU clock rate is 60MHz. The SYSCLKOUT, then, is 30MHz. If I wish my epwm generates an interrupt at a rate of 10kHz, dose it mean what I need to do is just set TBPRD register to be 3000?

    The counting mode I chose is up and down.

    Thanks.

    Jingzhe

  • Jingzhe Wu said:

    My device is F28027, therefore presumably the CPU clock rate is 60MHz. The SYSCLKOUT, then, is 30MHz.

     
    Not correct.  SYSCLKOUT is another name for the CPU clock rate.  They are the same thing.
     
    The reason there is a factor of 2 for up/down count mode is because you count up to the TxPRD value, and then you count down to zero.  Hence, the PWM period is twice the TxPRD register value.
     
    If SYSCLKOUT=60 MHz and you want 10 kHz symmetric PWM, you would set
     
    TxPRD = SYSCLKOUT/fPWM/2
                = (60 MHz)/(10 kHz)/2
                = 3000
     
    Regards,
    David
  • Hi Devin,

    I used to set my TBPRD value to be 5000 and it gives me a interrupt frequency of 6kHz. Then I set TBPRD to be 3000, the interrupt frequency remains at about 6kHz.

    In fact, I tried to reduce the value in TBPRD and I observed that the output frequency is always around 6kHz. On the contrary, I tried to increase the TBPRD value to say, 8000 and 12000. In this case, the interrupt frequency reduces as expected.

    I am wondering if 6kHz is the limit of interrupt? Probably my code is too long for the controller to run in the period of interrupt?

    Please help.

    Many thanks.

    Jingzhe

  • Jingzhe,

    Are you checking the PWM pin frequency on a scope?  This frequency will have nothing to do with the CPU executing the ISR.

    I'd doubt that you are not getting through the ISR in time, but I suppose it can happen.  Pulse a GPIO at the start of the ISR, and compare against the PWM pin signal on the scope.  That will tell you what is happening.

    - David

  • Hi David,

    What I did was merely to observe the waveform from CCS graph tool.

    Actually how exactly do I output the interruption triggering PWM and toggle GPIO? I mean what codes should I use?

    Do I just use pwm_update function as in the case of outputting inverter gating signals?

    Thank you. 

    Jingzhe

  • Jingzhe,

    I assumed you already have the PWM module configured, right?  So, you should be able to view the PWM signal on a scope provided you configured the GPIO pin mux for the PWM function.

    To view the ISR rate, just configure any spare GPIO pin as an output, and then set the pin high at the start of the ISR, and low at the end of the ISR.  For example:

    GpioDataRegs.GPBSET.bit.GPIO32 = 1;   // Set the pin high
    .
    .
    .
    GpioDataRegs.GPBCLEARGPIO32 = 1;      // Set the pin low

     

    - David

     

  • Hi David.

    Thanks for the help. I am still a bit confused about observing pwm interrupts. Indeed I configured the pwm module, but what I did was jus to initialise the module using a pwm initialisation function pwm_init().

    void F280X_PWM_Init(PWMGEN *p) {

                    // Init Timer-Base Period Register for EPWM1-EPWM3         

    EPwm1Regs.TBPRD = p->PeriodMax;         

    EPwm2Regs.TBPRD = p->PeriodMax;         

    EPwm3Regs.TBPRD = p->PeriodMax;   

     EPwm4Regs.TBPRD = p->PeriodMax;

             // Init Timer-Base Phase Register for EPWM1-EPWM3         

    EPwm1Regs.TBPHS.half.TBPHS = 0;         

    EPwm2Regs.TBPHS.half.TBPHS = 0;         

    EPwm3Regs.TBPHS.half.TBPHS = 0;   

    EPwm4Regs.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;   

     EPwm4Regs.TBCTL.all = PWM_INIT_STATE;

     EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; // Create sync event      

        EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN;  // Pass through         

    EPwm3Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN;  // Pass through         

    EPwm4Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN;   // Pass through

             // Allow each timer to be sync'ed         

    EPwm1Regs.TBCTL.bit.PHSEN = 0;    // master         

    EPwm2Regs.TBCTL.bit.PHSEN = 1;    // slave         

    EPwm3Regs.TBCTL.bit.PHSEN = 1;  // slave         

    EPwm4Regs.TBCTL.bit.PHSEN = 1;  // slave

             // 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;   

    EPwm4Regs.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;   

    EPwm4Regs.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 Falling/Rising Edge Delay Register 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;         

     EPwm4Regs.PCCTL.all = PCCTL_INIT_STATE;                   

     EALLOW;                    

             // Init Trip Zone Select Register         

     EPwm1Regs.TZSEL.all = TZSEL_INIT_STATE;         

     EPwm2Regs.TZSEL.all = TZSEL_INIT_STATE;         

    EPwm3Regs.TZSEL.all = TZSEL_INIT_STATE;         

    EPwm4Regs.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;   

     EPwm4Regs.TZCTL.all = TZCTL_INIT_STATE;

             // Setting six EPWM as primary output pins         

    GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1;   // EPWM1A pin         

    GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1;   // EPWM1B pin         

    GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 1;   // EPWM2A pin         

     GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 1;   // EPWM2B pin         

     GpioCtrlRegs.GPAMUX1.bit.GPIO4 = 1;   // EPWM3A pin         

    GpioCtrlRegs.GPAMUX1.bit.GPIO5 = 1;   // EPWM3B pin

             EDIS;             

    }

     

    The code is as above. Although the 6 GPIOs are configured to be pwm output pins, I don't think they output interrupt triggered by pwm because they just output constant 3.3V on GPIO 0 2 4. What codes should I include to pass the interrupt triggering signal to GPIOs?

     

    Also, I managed to observed   the ISR frequency by toggling the GPIO when the interrupt is 6kHz. I observed that the ISR takes over almost 90% of the interrupt period. Therefore it seems the program is too long for any higher interrupt frequencies. Probably because I include too many trigonometric and inverse trignometric functions that slow the program down?

    Thanks.

    Jingzhe

  • Jingzhe,

    I don't see you writing any values to the ePWM CMPx nor AQCTLx registers to configure the PWM signals.  You should look at the examples in ControlSuite.  For example, this one:

    C:\TI\controlSUITE\device_support\f2802x\v210\f2802x_examples\epwm_up_aq

    Regards,

    David