Hello,
I using a 28027 Piccolo processor to control an AC-AC Cuk SMPS. During the 60Hz cycle I change the PWM switching methodology 5 times through the period. This is done to reduce the switching violations for the Cuk topology and reduce switching losses. During two of the switching states I require 200nS RED/FED dead-band and the other three states require no dead-band. I am using two PWM's configured as master slave, shadow register, and dead-band mode. I control the switching states by loading the PWM's with a PWM period or 100% duty cycle for always "on" or 0% duty cycle for always "off". When I do not require dead-band I set the dead-band register to 0. When I require dead-band I set both to 200nS. My problem I am having is during the last switching period of one of the phases that require dead-band, the first rising/falling edge will have dead-band. The last rising/falling edge will not have any dead-band. I believe the issue is due to the fact the PWM registers get set by the shadow register at the end of the period. The RED/FED registers get set immediately and influence the next rising/falling edge. Is their any way to set the PWM registers with a new PWM value and modify the RED/FED registers and guarantee that the RED/FED values will stay active for that last PWM period? I have included 2 relevant snippets of my code. The first is the set-up of the PWM's. The second snippet is the ADC EOC isr routine that generates the compensation network results, loads the PWM value or sets high/low the PWM depending on the state, and sets up the RED/FED registers.
PWM Initialization
//=====================================================================
// Configure PWM1x
//=====================================================================
//Disable Clocks
CLK_disableTbClockSync(myClk);
// Set up clock source for EPWM1x
CLK_enablePwmClock(myClk, PWM_Number_1);
// Configure GPIO 0 & 1 as PWM1A/PWM1B
GPIO_setPullUp(myGpio, GPIO_Number_0, GPIO_PullUp_Enable);
GPIO_setPullUp(myGpio, GPIO_Number_1, GPIO_PullUp_Enable);
GPIO_setMode(myGpio, GPIO_Number_0, GPIO_0_Mode_EPWM1A);
GPIO_setMode(myGpio, GPIO_Number_1, GPIO_1_Mode_EPWM1B);
// Set-up PWM1x
PWM_setPeriod(myPwm1, EPWM_PERIOD); // Set timer period
PWM_setPhase(myPwm1, 0x0000); // Phase is 0
PWM_setCount(myPwm1, 0x0000); // Clear counter
PWM_setCounterMode(myPwm1, PWM_CounterMode_UpDown); // Count up/down
PWM_disableCounterLoad(myPwm1); // Disable phase loading
PWM_setHighSpeedClkDiv(myPwm1, PWM_HspClkDiv_by_1); // Clock ratio to SYSCLKOUT /1
PWM_setClkDiv(myPwm1, PWM_ClkDiv_by_1); // Set internal clock /1 -- One Clock Tick Equals 16.666nS
PWM_setSyncMode(myPwm1, PWM_SyncMode_CounterEqualZero); // Sets PWM1x as the master
PWM_setShadowMode_CmpA(myPwm1, PWM_ShadowMode_Shadow); // Load registers every zero
PWM_setShadowMode_CmpB(myPwm1, PWM_ShadowMode_Shadow);
PWM_setLoadMode_CmpA(myPwm1, PWM_LoadMode_Zero);
PWM_setLoadMode_CmpB(myPwm1, PWM_LoadMode_Zero);
// Set up Action Qualifier for PWM1
PWM_setDeadBandInputMode(myPwm1, PWM_DeadBandInputMode_EPWMxA_Rising_EPWMxB_Falling);
PWM_setDeadBandPolarity(myPwm1, PWM_DeadBandPolarity_EPWMxB_Inverted);
PWM_setDeadBandOutputMode(myPwm1, PWM_DeadBandOutputMode_EPWMxA_Rising_EPWMxB_Falling);
// Set compare actions for EPWM1A
PWM_setActionQual_CntUp_CmpA_PwmA(myPwm1, PWM_ActionQual_Clear);
PWM_setActionQual_CntDown_CmpA_PwmA(myPwm1, PWM_ActionQual_Set);
// Set compare actions for EPWM1B
PWM_setActionQual_CntUp_CmpB_PwmB(myPwm1, PWM_ActionQual_Clear);
PWM_setActionQual_CntDown_CmpB_PwmB(myPwm1, PWM_ActionQual_Set);
// Set Dead-Band Delay
PWM_setDeadBandRisingEdgeDelay(myPwm1, EPWM1_ZERO_DEADBAND);
PWM_setDeadBandFallingEdgeDelay(myPwm1, EPWM1_ZERO_DEADBAND);
//=====================================================================
// Configure PWM2x
//=====================================================================
// Enable master clock for PWM2x
CLK_enablePwmClock(myClk, PWM_Number_2);
// Configure GPIO 2 & 3 as PWM2A/PWM2B
GPIO_setPullUp(myGpio, GPIO_Number_2, GPIO_PullUp_Enable);
GPIO_setPullUp(myGpio, GPIO_Number_3, GPIO_PullUp_Enable);
GPIO_setMode(myGpio, GPIO_Number_2, GPIO_2_Mode_EPWM2A);
GPIO_setMode(myGpio, GPIO_Number_3, GPIO_3_Mode_EPWM2B);
// Set-up PWM2x
PWM_setPeriod(myPwm2, EPWM_PERIOD); // Set timer period
PWM_setPhase(myPwm2, 0x0000); // Phase is 0
PWM_setCount(myPwm2, 0x0000); // Clear counter
PWM_setCounterMode(myPwm2, PWM_CounterMode_UpDown); // Count up/down
PWM_disableCounterLoad(myPwm2); // Disable phase loading
PWM_setHighSpeedClkDiv(myPwm2, PWM_HspClkDiv_by_1); // Clock ratio to SYSCLKOUT /1
PWM_setClkDiv(myPwm2, PWM_ClkDiv_by_1); // Set internal clock /1 -- One clock tick equals 16.666nS
PWM_setSyncMode(myPwm2, PWM_SyncMode_EPWMxSYNC); // Sets PWM2x as a slave
PWM_setShadowMode_CmpA(myPwm2, PWM_ShadowMode_Shadow); // Load registers every zero
PWM_setShadowMode_CmpB(myPwm2, PWM_ShadowMode_Shadow);
PWM_setLoadMode_CmpA(myPwm2, PWM_LoadMode_Zero);
PWM_setLoadMode_CmpB(myPwm2, PWM_LoadMode_Zero);
// Set up Action Qualifier for PWM2
PWM_setDeadBandInputMode(myPwm2, PWM_DeadBandInputMode_EPWMxA_Rising_EPWMxB_Falling);
PWM_setDeadBandPolarity(myPwm2, PWM_DeadBandPolarity_EPWMxB_Inverted);
PWM_setDeadBandOutputMode(myPwm2, PWM_DeadBandOutputMode_EPWMxA_Rising_EPWMxB_Falling);
// Set compare actions for EPWM2A
PWM_setActionQual_CntUp_CmpA_PwmA(myPwm2, PWM_ActionQual_Clear);
PWM_setActionQual_CntDown_CmpA_PwmA(myPwm2, PWM_ActionQual_Set);
// Set compare actions for EPWM2B
PWM_setActionQual_CntUp_CmpB_PwmB(myPwm2, PWM_ActionQual_Clear);
PWM_setActionQual_CntDown_CmpB_PwmB(myPwm2, PWM_ActionQual_Set);
// Set Dead-Band Delay
PWM_setDeadBandRisingEdgeDelay(myPwm2, EPWM2_ZERO_DEADBAND);
PWM_setDeadBandFallingEdgeDelay(myPwm2, EPWM2_ZERO_DEADBAND);
Code that modifies the PWM's and FED/RED's
//=====================================================================
// ADC/PWM Duty Cycle Manager Thread
//
// Note: Discard ADCRESULT0 as part of workaround to silicon errata rev0
//=====================================================================
interrupt void adc_eoc_isr(void) {
if (SystemSynchronization) {
// Get ADC input value & convert to q24 format
iq_AdcOut = _IQabs(((_iq)AdcResult.ADCRESULT2 << 12) - iq_VOFFSET);
// Multiply by 2 to get full range (000 - FFF) and save for 3p3z method
Fdbk = _IQmpy2(iq_AdcOut);
// Get Sin Table Value and muliply by desired reference voltage constant
iq_SinValue = _IQabs(_IQmpy(IQ24_HEX_nSIN_TABLE[SinTablePointer], iq_VOUT));
if (SoftStart) {
// In SoftStart so slow ramp the Reference Value & save for 3p3z method
Ref = _IQmpy(iq_SinValue, iq_SoftRatio);
}
else {
// No SoftStart so just update normal Reference Value & save for 3p3z method
Ref = iq_SinValue;
}
// Go execute 3p3z Gc
CNTL_3P3Z();
// Generate PWM
iq_D1 = _IQmpy(Out, iq_PWM_MAXIMUM);
// Convert Fixed Point Fractional PWM to Integer PWM
EpwmDutyCycle = (int)(iq_D1 >> 12);
// Make sure Duty Cycle is not violating the maximum voltage boost
if (EpwmDutyCycle >= MAX_SATURATION) {
EpwmDutyCycle = MAX_SATURATION;
}
DINT;
switch (AcPhaseState) {
case 0: // State 0 -- Diagnostic Flip-Flop
// No Dead-band for Flip-Flop
EPwm2Regs.DBFED = EPWM2_ZERO_DEADBAND;
EPwm2Regs.DBRED = EPWM2_ZERO_DEADBAND;
// Set up commutation for Flip-Flop
EPwm1Regs.CMPA.half.CMPA = EpwmDutyCycle;
EPwm1Regs.CMPB = EpwmDutyCycle;
EPwm2Regs.CMPA.half.CMPA = EpwmDutyCycle;
EPwm2Regs.CMPB = EpwmDutyCycle;
break;
case 1: // State 1 -- Flip-Flop
// Update PWM's for Flip-Flop
EPwm1Regs.CMPA.half.CMPA = EpwmDutyCycle;
EPwm1Regs.CMPB = EpwmDutyCycle;
EPwm2Regs.CMPA.half.CMPA = EpwmDutyCycle;
EPwm2Regs.CMPB = EpwmDutyCycle;
break;
case 2: // State 2 -- +Synchronous
// Update Dead-band
EPwm1Regs.DBFED = EPWM1_FED;
EPwm1Regs.DBRED = EPWM1_RED;
// Set comutation to +Synchronous
EPwm2Regs.CMPA.half.CMPA = EPWM2A_ON;
EPwm2Regs.CMPB = EPWM2B_ON;
// Update PWM's
EPwm1Regs.CMPA.half.CMPA = EpwmDutyCycle;
EPwm1Regs.CMPB = EpwmDutyCycle;
break;
case 3: // State 3 -- Flip-Flop
// No Dead-Band for Flip-Flop
EPwm1Regs.DBFED = EPWM1_ZERO_DEADBAND;
EPwm1Regs.DBRED = EPWM1_ZERO_DEADBAND;
// Set up PWM's for Flip-Flop
EPwm1Regs.CMPA.half.CMPA = EpwmDutyCycle;
EPwm1Regs.CMPB = EpwmDutyCycle;
EPwm2Regs.CMPA.half.CMPA = EpwmDutyCycle;
EPwm2Regs.CMPB = EpwmDutyCycle;
break;
case 4: // State 4 -- -Synchronous
// Update Dead-band
EPwm2Regs.DBFED = EPWM2_FED;
EPwm2Regs.DBRED = EPWM2_RED;
// Set comutation to +Synchronous
EPwm1Regs.CMPA.half.CMPA = EPWM1A_ON;
EPwm1Regs.CMPB = EPWM1B_ON;
// Update PWM's
EPwm2Regs.CMPA.half.CMPA = EpwmDutyCycle;
EPwm2Regs.CMPB = EpwmDutyCycle;
break;
}
EINT;
// Bump Sin Table Pointer
++SinTablePointer;
// Reset pointer if at end of array
if (SinTablePointer == 399) SinTablePointer = 0;
}
// Clear ADCINT1 flag reinitialize for next SOC
AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;
// Acknowledge interrupt to PIE
PieCtrlRegs.PIEACK.all = PIEACK_GROUP10;
}