Hello to everyone,
I am trying to program my C2000 launchpad in order to have an spwm with 2kHz switching frequency and 50Hz sine wave. The spwm must be for a 3 phase inverter with 120deg difference between each phase. My program read the sine table, which is stored in the ROM, and sets the CMPA register for the three EPWM when the timer0 gives an interrupt (every 20ms/512). Then I set the phase shift to be 120deg for each EPWM module. But the phase voltage as well as the line voltage from my inverter is not correct. The idea of having a delay on each EPWM is the same, as having three different sine waves with 120deg difference in order to set each CMPA registers?
Here is my code: please free to comment for any mistakes or advices. Thanks in advance.
//-----------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------
//
//
//
// The user sets the frequency of the SPWM by setting appropriately the
// EPWM1_TIMER_TBPRD variable. The frequency of the PWM,up and down mode,
// obeys the equations: TPWM=2xTBPRDxTTBCLK, TTBCLK=SYSCLKOUT/(HSPCLKDIVxCLKDIV).
// By default: HSPCLKDIV=2, CLKDIV=1.
//
// The sine for the PWM is read by the chip ROM. The sine table consists of
// 512 elements.
// The frequency of sinusoidal PWM is defined by the period of the timer0 interrupt.
// For 50Hz the sine table must be read, entirely in 20msec. This means that the
// timer0 interrupt must occur in every 20/512 msec.
// The general type for the Ttimer=Tsin*Fcpu/index.
//
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
#include <stdio.h>
#include <file.h>
#include "DSP28x_Project.h" // DSP28x Headerfile
#include "f2802x_common/include/F2802x_GlobalPrototypes.h"
#include "f2802x_common/include/pll.h"
#include "f2802x_common/include/clk.h"
#include "f2802x_common/include/wdog.h"
#include "f2802x_common/include/flash.h"
#include "f2802x_common/include/gpio.h"
#include "f2802x_common/include/pie.h"
#include "f2802x_common/include/adc.h"
#include "f2802x_common/include/sci.h"
#include "f2802x_common/include/sci_io.h"
#include "f2802x_common/include/pwm.h"
#include "f2802x_common/include/timer.h"
#include "f2802x_common/include/IQmathLib.h" //IQmath Library header file
extern void DSP28x_usDelay(Uint32 Count);
#pragma DATA_SECTION(sine_table,"IQmathTables"); //IQmath ROM sine table
_iq30 sine_table[512];
//Interrupt prototype function for timer0
interrupt void cpu_timer0_isr(void);
void update_compare(void);
//Global PWM variables
#define EPWM1_TIMER_TBPRD 14634 // Period register for 2050.2Hz
#define PHASE 120.0 // Defines the real in degrees phase between phases, 120deg
#define TTIMERREG 2343 // Timer interrupt for 50Hz SPWM
Uint16 EPWM_PHASE=(EPWM1_TIMER_TBPRD*PHASE/180.0); //The phase as seen from the EPWM module
Uint16 duty_cycle_A=1000; // Set duty 50% initially
Uint16 duty_cycle_B=1000; // Set duty 50% initially
Uint16 index=0;
Uint16 DEADTIME_R=5.0;
Uint16 DEADTIME_F=5.0;
Uint16 y=0.0;
// Handles setup
CPU_Handle myCpu;
PLL_Handle myPll;
WDOG_Handle myWDog;
CLK_Handle myClk;
ADC_Handle myAdc;
FLASH_Handle myFlash;
GPIO_Handle myGpio;
PIE_Handle myPie;
SCI_Handle mySci;
PWM_Handle PWMA,PWMB,PWMC;
TIMER_Handle myTimer0;
// Handles initialization
void setup_handles()
{
myClk = CLK_init((void *)CLK_BASE_ADDR, sizeof(CLK_Obj));
myPll = PLL_init((void *)PLL_BASE_ADDR, sizeof(PLL_Obj));
myWDog = WDOG_init((void *)WDOG_BASE_ADDR, sizeof(WDOG_Obj));
myCpu = CPU_init((void *)NULL, sizeof(CPU_Obj));
myFlash = FLASH_init((void *)FLASH_BASE_ADDR, sizeof(FLASH_Obj));
myGpio = GPIO_init((void *)GPIO_BASE_ADDR, sizeof(GPIO_Obj));
myPie = PIE_init((void *)PIE_BASE_ADDR, sizeof(PIE_Obj));
mySci = SCI_init((void *)SCIA_BASE_ADDR, sizeof(SCI_Obj));
myAdc = ADC_init((void *)ADC_BASE_ADDR, sizeof(ADC_Obj));
PWMA = PWM_init((void *)PWM_ePWM1_BASE_ADDR, sizeof(PWM_Obj));
PWMB = PWM_init((void *)PWM_ePWM2_BASE_ADDR, sizeof(PWM_Obj));
PWMC = PWM_init((void *)PWM_ePWM3_BASE_ADDR, sizeof(PWM_Obj));
myTimer0 = TIMER_init((void *)TIMER0_BASE_ADDR, sizeof(TIMER_Obj));
}
//System Initialization
void init_system()
{
//Disable watchcdog
WDOG_disable(myWDog);
//Device calibration for the adc
(*Device_cal)();
//Sets the internal oscillator source
CLK_setOscSrc(myClk, CLK_OscSrc_Internal);
// Setup the PLL for x10 /2 which will yield 60Mhz = 10Mhz * 12 / 2
PLL_setup(myPll, PLL_Multiplier_12, PLL_DivideSelect_ClkIn_by_2);
//Disable the PIE peripheral and all the interupts
PIE_disable(myPie);
PIE_disableAllInts(myPie);
CPU_disableGlobalInts(myCpu);
CPU_clearIntFlags(myCpu);
#ifdef _FLASH
memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
#endif
}
//GPIO initialization
void gpio_init()
{
// Initialize GPIO for the EPWM1A and EPWM1B
GPIO_setPullUp(myGpio, GPIO_Number_0, GPIO_PullUp_Disable);
GPIO_setPullUp(myGpio, GPIO_Number_1, GPIO_PullUp_Disable);
GPIO_setMode(myGpio, GPIO_Number_0, GPIO_0_Mode_EPWM1A);
GPIO_setMode(myGpio, GPIO_Number_1, GPIO_1_Mode_EPWM1B);
GPIO_setDirection(myGpio,GPIO_Number_0,GPIO_Direction_Output);
GPIO_setDirection(myGpio,GPIO_Number_1,GPIO_Direction_Output);
// Initialize GPIO for the EPWM2A and EPWM2B
GPIO_setPullUp(myGpio, GPIO_Number_2, GPIO_PullUp_Disable);
GPIO_setPullUp(myGpio, GPIO_Number_3, GPIO_PullUp_Disable);
GPIO_setMode(myGpio, GPIO_Number_2, GPIO_2_Mode_EPWM2A);
GPIO_setMode(myGpio, GPIO_Number_3, GPIO_3_Mode_EPWM2B);
GPIO_setDirection(myGpio,GPIO_Number_2,GPIO_Direction_Output);
GPIO_setDirection(myGpio,GPIO_Number_3,GPIO_Direction_Output);
// Initialize GPIO for the EPWM2A and EPWM2B
GPIO_setPullUp(myGpio, GPIO_Number_4, GPIO_PullUp_Disable);
GPIO_setPullUp(myGpio, GPIO_Number_5, GPIO_PullUp_Disable);
GPIO_setMode(myGpio, GPIO_Number_4, GPIO_4_Mode_EPWM3A);
GPIO_setMode(myGpio, GPIO_Number_5, GPIO_5_Mode_EPWM3B);
GPIO_setDirection(myGpio,GPIO_Number_4,GPIO_Direction_Output);
GPIO_setDirection(myGpio,GPIO_Number_5,GPIO_Direction_Output);
}
//PWM settings
void pwma_init()
{
// PWMA initialization
CLK_enablePwmClock(myClk, PWM_Number_1);
//PWMA initialiazation
// Setup TBCLK
PWM_setCounterMode(PWMA,PWM_CounterMode_UpDown); // Count up-down
PWM_setPeriod(PWMA,EPWM1_TIMER_TBPRD); // Set timer period
PWM_disableCounterLoad(PWMA); // Disable phase loading
PWM_setSyncMode(PWMA,PWM_SyncMode_CounterEqualZero);
PWM_setPhase(PWMA,0x0000); // Phase is 0
PWM_setCount(PWMA, 0x0000); // Clear counter
PWM_setClkDiv(PWMA, PWM_ClkDiv_by_1);
PWM_setHighSpeedClkDiv(PWMA, PWM_HspClkDiv_by_1); // Clock ratio to SYSCLKOUT
// Setup shadowing
PWM_setShadowMode_CmpA(PWMA, PWM_ShadowMode_Shadow);
PWM_setShadowMode_CmpB(PWMA, PWM_ShadowMode_Shadow);
PWM_setLoadMode_CmpA(PWMA, PWM_LoadMode_Zero);
PWM_setLoadMode_CmpB(PWMA, PWM_LoadMode_Zero);
PWM_setCmpA(PWMA,1000); //Initial duty cycle
PWM_setCmpB(PWMA,1000);
// Set actions
PWM_setActionQual_CntUp_CmpA_PwmA(PWMA, PWM_ActionQual_Set); // Set PWM1A on event A, up count
PWM_setActionQual_CntDown_CmpA_PwmA(PWMA, PWM_ActionQual_Clear); // Clear PWM1A on event A, down count
PWM_setActionQual_CntUp_CmpB_PwmB(PWMA, PWM_ActionQual_Clear); // Set PWM1B on event B, up count
PWM_setActionQual_CntDown_CmpB_PwmB(PWMA, PWM_ActionQual_Set); // Clear PWM1B on event B, down count
//Set DeadBand Control
PWM_setDeadBandOutputMode(PWMA, PWM_DeadBandOutputMode_EPWMxA_Rising_EPWMxB_Falling);
PWM_setDeadBandPolarity(PWMA, PWM_DeadBandPolarity_EPWMxB_Inverted);
PWM_setDeadBandInputMode(PWMA, PWM_DeadBandInputMode_EPWMxA_Rising_and_Falling);
PWM_setDeadBandRisingEdgeDelay(PWMA, DEADTIME_R);
PWM_setDeadBandFallingEdgeDelay(PWMA, DEADTIME_F);
//--------------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------------------
//PWMB initialization
CLK_enablePwmClock(myClk, PWM_Number_2);
// Setup TBCLK
PWM_setCounterMode(PWMB,PWM_CounterMode_UpDown); // Count up-down
PWM_setPeriod(PWMB,EPWM1_TIMER_TBPRD); // Set timer period
PWM_enableCounterLoad(PWMB);
PWM_setPhaseDir(PWMB,PWM_PhaseDir_CountDown);
PWM_setSyncMode(PWMB,PWM_SyncMode_EPWMxSYNC);
PWM_setPhase(PWMB,EPWM_PHASE); // Phase is 120 degrees
PWM_setCount(PWMB, 0x0000); // Clear counter
PWM_setClkDiv(PWMB, PWM_ClkDiv_by_1);
PWM_setHighSpeedClkDiv(PWMB, PWM_HspClkDiv_by_1); // Clock ratio to SYSCLKOUT
// Setup shadowing
PWM_setShadowMode_CmpA(PWMB, PWM_ShadowMode_Shadow);
PWM_setShadowMode_CmpB(PWMB, PWM_ShadowMode_Shadow);
PWM_setLoadMode_CmpA(PWMB, PWM_LoadMode_Zero);
PWM_setLoadMode_CmpB(PWMB, PWM_LoadMode_Zero);
PWM_setCmpA(PWMB,1000); //Initial duty cycle
PWM_setCmpB(PWMB,1000);
// Set actions
PWM_setActionQual_CntUp_CmpA_PwmA(PWMB, PWM_ActionQual_Set); // Set PWM2A on event A, up count
PWM_setActionQual_CntDown_CmpA_PwmA(PWMB, PWM_ActionQual_Clear); // Clear PWM2A on event A, down count
PWM_setActionQual_CntUp_CmpB_PwmB(PWMB, PWM_ActionQual_Clear); // Set PWM2B on event B, up count
PWM_setActionQual_CntDown_CmpB_PwmB(PWMB, PWM_ActionQual_Set); // Clear PWM2B on event B, down count
//Set DeadBand Control
PWM_setDeadBandOutputMode(PWMB, PWM_DeadBandOutputMode_EPWMxA_Rising_EPWMxB_Falling);
PWM_setDeadBandPolarity(PWMB, PWM_DeadBandPolarity_EPWMxB_Inverted);
PWM_setDeadBandInputMode(PWMB, PWM_DeadBandInputMode_EPWMxA_Rising_and_Falling);
PWM_setDeadBandRisingEdgeDelay(PWMB, DEADTIME_R);
PWM_setDeadBandFallingEdgeDelay(PWMB, DEADTIME_F);
//---------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------
//PWMC initialization
CLK_enablePwmClock(myClk, PWM_Number_3);
// Setup TBCLK
PWM_setCounterMode(PWMC,PWM_CounterMode_UpDown); // Count up-down
PWM_setPeriod(PWMC,EPWM1_TIMER_TBPRD); // Set timer period
PWM_enableCounterLoad(PWMC);
PWM_setPhaseDir(PWMC,PWM_PhaseDir_CountUp);
PWM_setSyncMode(PWMC,PWM_SyncMode_EPWMxSYNC);
PWM_setPhase(PWMC,EPWM_PHASE); // Phase is 120
PWM_setCount(PWMC, 0x0000); // Clear counter
PWM_setClkDiv(PWMC, PWM_ClkDiv_by_1);
PWM_setHighSpeedClkDiv(PWMC, PWM_HspClkDiv_by_1); // Clock ratio to SYSCLKOUT
// Setup shadowing
PWM_setShadowMode_CmpA(PWMC, PWM_ShadowMode_Shadow);
PWM_setShadowMode_CmpB(PWMC, PWM_ShadowMode_Shadow);
PWM_setLoadMode_CmpA(PWMC, PWM_LoadMode_Zero);
PWM_setLoadMode_CmpB(PWMC, PWM_LoadMode_Zero);
PWM_setCmpA(PWMC,1000); //Initial duty cycle
PWM_setCmpB(PWMC,1000);
// Set actions
PWM_setActionQual_CntUp_CmpA_PwmA(PWMC, PWM_ActionQual_Set); // Set PWM3A on event A, up count
PWM_setActionQual_CntDown_CmpA_PwmA(PWMC, PWM_ActionQual_Clear); // Clear PWM3A on event A, down count
PWM_setActionQual_CntUp_CmpB_PwmB(PWMC, PWM_ActionQual_Clear); // Set PWM3B on event B, up count
PWM_setActionQual_CntDown_CmpB_PwmB(PWMC, PWM_ActionQual_Set); // Clear PWM3B on event B, down count
//Set DeadBand Control
PWM_setDeadBandOutputMode(PWMC, PWM_DeadBandOutputMode_EPWMxA_Rising_EPWMxB_Falling);
PWM_setDeadBandPolarity(PWMC, PWM_DeadBandPolarity_EPWMxB_Inverted);
PWM_setDeadBandInputMode(PWMC, PWM_DeadBandInputMode_EPWMxA_Rising_and_Falling);
PWM_setDeadBandRisingEdgeDelay(PWMC, DEADTIME_R);
PWM_setDeadBandFallingEdgeDelay(PWMC, DEADTIME_F);
CLK_enableTbClockSync(myClk);
}
//PIE settings
void pie_init()
{
PIE_enable(myPie);
EALLOW;
EDIS;
PIE_registerPieIntHandler(myPie, PIE_GroupNumber_1, PIE_SubGroupNumber_7, (intVec_t)&cpu_timer0_isr);
EDIS;
}
//Timer settings
void timer0_init()
{
TIMER_stop(myTimer0);
TIMER_setPeriod(myTimer0,TTIMERREG);
TIMER_setPreScaler(myTimer0,0);
TIMER_reload(myTimer0);
TIMER_setEmulationMode(myTimer0, TIMER_EmulationMode_StopAfterNextDecrement);
TIMER_enableInt(myTimer0);
TIMER_start(myTimer0);
}
void main()
{
setup_handles();
init_system();
gpio_init();
pwma_init();
pie_init();
timer0_init();
//Enables the CPU interrupt
CPU_enableInt(myCpu, CPU_IntNumber_1);
//Enables the interrupt of the Timer0 for the PIE module
PIE_enableTimer0Int(myPie);
CPU_enableGlobalInts(myCpu);
CPU_enableDebugInt(myCpu);
//Forever Loop to see the results
for(;;)
{
}
}
interrupt void cpu_timer0_isr(void)
{
update_compare();
// Acknowledge this interrupt to receive more interrupts from group 1
PIE_clearInt(myPie, PIE_GroupNumber_1);
}
void update_compare(void)
{
PWM_setCmpA(PWMA,_IQsat(_IQ30mpy((sine_table[index]+_IQ30(0.9999))/2,EPWM1_TIMER_TBPRD),EPWM1_TIMER_TBPRD,0));
PWM_setCmpB(PWMA,_IQsat(_IQ30mpy((sine_table[index]+_IQ30(0.9999))/2,EPWM1_TIMER_TBPRD),EPWM1_TIMER_TBPRD,0));
PWM_setCmpA(PWMB,_IQsat(_IQ30mpy((sine_table[index]+_IQ30(0.9999))/2,EPWM1_TIMER_TBPRD),EPWM1_TIMER_TBPRD,0));
PWM_setCmpB(PWMB,_IQsat(_IQ30mpy((sine_table[index]+_IQ30(0.9999))/2,EPWM1_TIMER_TBPRD),EPWM1_TIMER_TBPRD,0));
PWM_setCmpA(PWMC,_IQsat(_IQ30mpy((sine_table[index]+_IQ30(0.9999))/2,EPWM1_TIMER_TBPRD),EPWM1_TIMER_TBPRD,0));
PWM_setCmpB(PWMC,_IQsat(_IQ30mpy((sine_table[index]+_IQ30(0.9999))/2,EPWM1_TIMER_TBPRD),EPWM1_TIMER_TBPRD,0));
if (index++ >511) index = 0;
}
//---------------------------------------------
