Hi,
I was talking to Nima Eskandari but the thread is closed, so I try making this related question, instead.
Hi Nima, here I am, bothering you again... I hope, we can reopen the thread!
To continue with the interrupts question, "TMS320F28379D: ePWM interrupts on TBCTR = CMPA and also on TBCTR = CMPB",
I have made my tests and your idea works good, but I found out that I can also use Period on ePWMxA and CMPB on the ePWMxB to generate the interrupts I need. It seems to be more simple...
However, the timing does not work as I expected:
Interrupts A and B on ePWM2 are supposed to activate an interrupt on ePWM1, which clears GPIO56 pin to low, just after the A-pin of the ePWM1 goes high.
Ideally, this should happen after around 5 uS, but this is not so crucial, as long as this remains allways the same.
The interrupts are working, but the timing not.
GPIO56 goes low at any moment, but not on the moment I want.
My logic analyzer shows, also, that the interrupts of ePWM2 are comming some (randomly) 4 till 7 uS before the changing to Low or High happens on the ePWM2-output A,
while I am expecting it just on this time or slightly after, but not before.
So, I have two questions:
1 - Why does the interrupt comes so far before the time it should come?
This is, so far, not so disturbing for my application, but:
2 - Why is Pin56 going low randomly in time?
I know, there is a propagation delay of around 14 SYSCLK till the ISR is called, but this does not explain this behaviour.
Te relevant parts of the code are included.
I wish you a nice weekend, or, better, a nice week!
Gustavo
myPeriod = 730; // Freq = 67,8 kHz, Period 14,75 uS myDutyA = 718; // duty is 98,31% myDutyB = 50; myDutyFineA = 1; myDutyFineB = 1; myPeriodGrand = 786; myDutyGrand = 451; // // epwm1_isr // __interrupt void epwm1_isr(void) { EPwm1Regs.ETSEL.bit.INTEN = 0; // Disable ePWM1 INT, until epwm2_isr enables it again GpioDataRegs.GPBCLEAR.bit.GPIO61 = 1; // This should allways happen at the same place, ideally 6uS after ePWM1 goes High (which, in turn, remains High during 14,38 uS) DELAY_US(100); // this is only for clarity. Here is some code GpioDataRegs.GPBSET.bit.GPIO61 = 1; // set GPIO61 high if(modo == 0b110) { modo = 0b010; // 100: time-base counter equal to CMPA when the timer is incrementing DELAY_US(5); // Here is some code } else { modo = 0b110; // 110: time-base counter equal to CMPB when the timer is incrementing DELAY_US(5); // Here is some code } EPwm2Regs.ETSEL.bit.INTSEL = modo; PieCtrlRegs.PIEACK.all = PIEACK_GROUP3; // Acknowledge this interrupt to receive more interrupts from group 3 } // // epwm2_isr __interrupt void epwm2_isr(void) { EPwm1Regs.ETCLR.bit.INT = 1; // Clear INT flag for ePWM1 timer EPwm1Regs.ETSEL.bit.INTEN = 1; // Enable INT on ePWM1 EPwm2Regs.ETCLR.bit.INT = 1; // Clear INT flag for this timer PieCtrlRegs.PIEACK.all = PIEACK_GROUP3; // Acknowledge this interrupt to receive more interrupts from group 3 } void HRPWM1_Config(myPeriod) { EPwm1Regs.TBCTL.bit.PRDLD = TB_IMMEDIATE; // set Immediate load EPwm1Regs.TBPRD = myPeriod; // PWM frequency EPwm1Regs.CMPA.bit.CMPA = myDutyA; // set duty for ePWM1A EPwm1Regs.CMPA.bit.CMPAHR = (myDutyFineA << 8); // set duty fine for ePWM1A EPwm1Regs.CMPB.bit.CMPB = myDutyB; // set duty for ePWM1B - for the interrupt EPwm1Regs.CMPB.all |= (myDutyFineB << 8); // set HR-duty for ePWM1B - for the interrupt EPwm1Regs.TBPHS.all = 0; EPwm1Regs.TBCTR = 0; EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE; EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1; EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET; EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; EPwm1Regs.AQCTLB.bit.ZRO = AQ_SET; EPwm1Regs.AQCTLB.bit.CBU = AQ_CLEAR; // INT on CMPB EPwm1Regs.ETSEL.bit.INTEN = 0; // Disable INT - It will be enabled in epwm2_isr EPwm1Regs.ETPS.bit.INTPSSEL = 0x0; EPwm1Regs.ETPS.bit.INTPRD = 0x2; // Generate an interrupt on the second event EPwm1Regs.ETSEL.bit.INTSELCMP = 0x0; // 0: time-base counter equal to CMPB when the timer is incrementing EPwm1Regs.ETSEL.bit.INTSEL = 0x6; // 110: time-base counter equal to CMPB. EALLOW; EPwm1Regs.HRCNFG.all = 0x0; EPwm1Regs.HRCNFG.bit.EDGMODE = HR_FEP; EPwm1Regs.HRCNFG.bit.CTLMODE = HR_CMP; EPwm1Regs.HRCNFG.bit.HRLOAD = HR_CTR_ZERO; EPwm1Regs.HRCNFG.bit.EDGMODEB = HR_FEP; EPwm1Regs.HRCNFG.bit.CTLMODEB = HR_CMP; EPwm1Regs.HRCNFG.bit.HRLOADB = HR_CTR_ZERO; EDIS; } // // HRPWM2_Config // void HRPWM2_Config(period) // low freq. { EPwm2Regs.TBCTL.bit.PRDLD = TB_IMMEDIATE; // set Immediate load EPwm2Regs.TBPRD = myPeriodGrand; // PWM frequency EPwm2Regs.CMPB.bit.CMPB = myDutyGrand; // set duty EPwm2Regs.CMPA.bit.CMPA = myDutyGrand; // set duty ???? EPwm2Regs.TBPHS.all = 0; EPwm2Regs.TBCTR = 0; EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Start ePWM in COUNT_UP mode EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE; EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE; EPwm2Regs.TBCTL.bit.HSPCLKDIV = 0b100; // to have a very low freq EPwm2Regs.TBCTL.bit.CLKDIV = 0x4; // Time Base Clock Pre-Scale EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; EPwm2Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm2Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm2Regs.AQCTLA.bit.ZRO = AQ_SET; EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR; EPwm2Regs.AQCTLB.bit.ZRO = AQ_SET; EPwm2Regs.AQCTLB.bit.CBU = AQ_CLEAR; // need INT on CMPB and on Period: EPwm2Regs.ETPS.bit.INTPSSEL = 0x0; EPwm2Regs.ETPS.bit.INTPRD = 0x1; // 01: Generate an interrupt on the first event INTCNT = 01 (first event) EPwm2Regs.ETSEL.bit.INTSELCMP = 0x0; // time-base counter equal to CMPA or CMPB when the timer is incrementing to INTSEL selection mux. EPwm2Regs.ETSEL.bit.INTSEL = modo; // start with 110: time-base counter equal to CMPB. In the epwm1_isr swap ot between 010 (for Period) and 110 (for CMPB) // I do not use HRPWM here. I guess I do not need this? // EALLOW; // EPwm2Regs.HRCNFG.all = 0x0; // EPwm2Regs.HRCNFG.bit.EDGMODE = HR_FEP; // EPwm2Regs.HRCNFG.bit.CTLMODE = HR_CMP; // EPwm2Regs.HRCNFG.bit.HRLOAD = HR_CTR_ZERO; // EPwm2Regs.HRCNFG.bit.EDGMODEB = HR_FEP; // EPwm2Regs.HRCNFG.bit.CTLMODEB = HR_CMP; // EPwm2Regs.HRCNFG.bit.HRLOADB = HR_CTR_ZERO; // EDIS; }