Tool/software: Code Composer Studio
Dear,
I have written a program for the TMS320F28379D which is a basic control loop application using 4 complementary PWM signals EPwmRegs1...4, so 8 PWM outputs in total. The EPwmRegs5 pwm channel is configured and used to trigger the ADC in the middle of the switching period. The cycle essentially occurs as follows:
- ePwmRegs5.CMPB is set at half the switching period and triggers the ADC
- in the ADC isr routine, the measurements are processed (offset compensation and scaling) and a CLA routine is called to calculate the new duty cycles
- Also in the ADC isr routine, the new duty cycle values are loaded in EPwmRegs1...4.CMPA
The whole sequence runs properly if step 3 is omitted and I verified the duration of the whole cycle from measurement to control output. It takes 1027 cycles (5 us) on average to determine a new control setting from the measurements. In case I want to send the new duty cycle command to the EPwmRegs1.CMPA register, the routine halts and the ADC isr is no longer called. However, the processor's main loop continues operating, indicating that the processor is still functioning.
Could you please advice on the root cause of this error and how to solve it? I have included some code excerpts below for clarification.
Thanks for your help.
Giel
Set up of the PWM
(*ePWM[j]).TBCTL.bit.PRDLD = TB_SHADOW; // set Shadow load (enable PWM value at next switching cycle) (*ePWM[j]).TBPRD = period; // PWM frequency = 1/(2*TBPRD) //(*ePWM[j]).CMPA.bit.CMPA = period / 2; // set duty 50% initially (*ePWM[j]).CMPA.bit.CMPA = 0; // set duty 0% initially (*ePWM[j]).CMPA.bit.CMPAHR = (1 << 8); // initialize HRPWM extension (<< 8 means the shift to the left operand by 8 bits) (*ePWM[j]).CMPB.bit.CMPB = period / 2; // set duty 50% initially //(*ePWM[j]).CMPB.all |= 1; (*ePWM[j]).TBPHS.all = 0; (*ePWM[j]).TBCTR = 0; (*ePWM[j]).TBCTL.bit.PHSEN = 1; (*ePWM[j]).TBCTL.bit.CTRMODE = TB_COUNT_UP; // Select up count mode (ramp up) // count mode (*ePWM[j]).TBCTL.bit.SYNCOSEL = TB_SYNC_IN; // Synchronize ePwm clocks (*ePWM[j]).TBCTL.bit.HSPCLKDIV = TB_DIV1; (*ePWM[j]).TBCTL.bit.CLKDIV = TB_DIV1; // TBCLK = SYSCLKOUT (*ePWM[j]).TBCTL.bit.FREE_SOFT = 11; (*ePWM[j]).CMPCTL.bit.LOADAMODE = CC_CTR_PRD; // LOAD CMPA on CTR = 0 (*ePWM[j]).CMPCTL.bit.LOADBMODE = CC_CTR_PRD; (*ePWM[j]).CMPCTL.bit.SHDWAMODE = CC_SHADOW; // A shadow register stores the PWM settings until the next PWM cycle where they will be effectively applied (*ePWM[j]).CMPCTL.bit.SHDWBMODE = CC_SHADOW; (*ePWM[j]).AQCTLA.bit.ZRO = AQ_SET; // PWM toggle high/low (*ePWM[j]).AQCTLA.bit.CAU = AQ_CLEAR; (*ePWM[j]).AQCTLB.bit.ZRO = AQ_SET; // PWM toggle high/low (note: the bit DBCTL.bit.POLSEL further down specifies the complimentarity of the PWM channels signals) (*ePWM[j]).AQCTLB.bit.CAU = AQ_CLEAR;
Setup of the PWM to trigger the ADC
EPwm5Regs.ETSEL.bit.SOCASEL = ET_CTRU_CMPB; // Trigger SOC when counter equals CMPB which is set at half the switching period
EPwm5Regs.ETPS.bit.SOCAPRD = ET_1ST; // Generate pulse on every event
EPwm5Regs.ETSEL.bit.SOCAEN = 1; // Enable SOC on A group
Each ADC SOC channel is triggered by SOCA of EPwmRegs5
AdcaRegs.ADCSOC1CTL.bit.TRIGSEL = 13; //trigger on ePWM5 SOCA
ADC isr routine:
// Process measurements
CLA_process_measurements();
// Check protection limits
Protection();
// State machine
state_machine();
// Control law
RunControlLaw();
// Set duty cycle
//setDutyCycle(500,500,500,500);
//setDutyCycle(res3[2],res3[3],res3[4],res3[5]);
cycle_duration = CpuTimer0Regs.PRD.bit.LSW - CpuTimer0Regs.TIM.bit.LSW;
// Acknowledge interrupt
AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //clear INT1 flag
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
res3[2]...[5] are 4 duty cycles calculated by the CLA.
setDutyCycle:
//
// setDutyCycle - set the duty cycle of the converter
//
void setDutyCycle(Uint16 pwm1, Uint16 pwm2, Uint16 pwm3, Uint16 pwm4)
{
EPwm1Regs.CMPA.bit.CMPA = pwm1;
EPwm2Regs.CMPA.bit.CMPA = pwm2;
EPwm3Regs.CMPA.bit.CMPA = pwm3;
EPwm4Regs.CMPA.bit.CMPA = pwm4;
}