//***************************************************/ //File name: SVPWM.c //Function: Call 28335 internal PWM module to generate SVPWM output test file //Description: Input information uses a structure. When using it, changing the structure pointer can change the input signal. // The InitSvpwm() function provides PWM module initialization and corresponding PIE interrupt configuration. // The voltage signal in the stationary plane coordinate system is obtained through the park inverse transformation. // Update the comparator value in the PWM timer underflow interrupt, that is, update once every PWM cycle//********************************************************/ #include "DSP2833x_Device.h" // DSP2833x Headerfile Include File #include "DSP2833x_Examples.h" // DSP2833x Examples Include File #include "math.h" #include "float.h" extern Uint16 RamfuncsRunStart; extern Uint16 RamfuncsLoadStart; extern Uint16 RamfuncsLoadEnd; typedef struct { float ds; // Voltage signal in stationary plane coordinate system float qs; float ang; // Electrical angle Electrical angle = mechanical angle * pole pair number float de; // Voltage signal in rotating coordinate system float qe; }IPARK; IPARK ipark1={0,0,0,0.3,0.4}; // IPARK *v=&ipark1; //Change the pointer of the structure here to change the input void InitSvpwm(void); void InitEPwm1(void); void InitEPwm2(void); void InitEPwm3(void); interrupt void epwm1_isr(void); void ipark(IPARK *v); void svgen(IPARK *v); #define PRD 7500 // PWM period register #define PI 3.1415926 float tmr1,tmr2,tmr3; void main(void) { InitSysCtrl(); DINT; InitPieCtrl(); IER = 0x0000; IFR = 0x0000; InitPieVectTable(); MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart); //Flash operation
InitFlash(); InitSvpwm(); for(;;) { asm(" NOP"); } } void InitSvpwm(void) { InitEPwm1Gpio(); InitEPwm2Gpio(); InitEPwm3Gpio(); EALLOW; PieVectTable.EPWM1_INT = &epwm1_isr; EDIS; EALLOW; SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; EDIS; InitEPwm1(); InitEPwm2(); InitEPwm3(); EALLOW; SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; EDIS; IER |= M_INT3; // Enable interrupt EPWM INT1 located in PIE interrupt group 3.1 PieCtrlRegs.PIEIER3.bit.INTx1 = 1; EINT; ERTM; } interrupt void epwm1_isr(void) { // Update CMPA and CMPB register values svgen(&ipark1); EPwm1Regs.CMPA.half.CMPA=tmr1; EPwm2Regs.CMPA.half.CMPA=tmr2; EPwm3Regs.CMPA.half.CMPA=tmr3; EPwm1Regs.CMPB=tmr1; EPwm2Regs.CMPB=tmr2; EPwm3Regs.CMPB=tmr3; // Clear interrupt flag EPwm1Regs.ETCLR.bit.INT = 1; // Clear interrupt response PieCtrlRegs.PIEACK.all = PIEACK_GROUP3; } void ipark(IPARK *v) { float ang; ang=(v->ang/360)*2*PI; //Convert angle to radians v->ds=v->de*cos(ang)-v->qe*sin(ang); //Get the d-axis voltage in the stationary plane coordinate system v->qs=v->qe*cos(ang)+v->de*sin(ang); //Get the q-axis voltage in the stationary plane coordinate system } void svgen(IPARK *v) { float Va,Vb,Vc,t1,t2,Ta,Tb,Tc; Uint32 sector=0; // sector=a+2b+4c Sector status indication Note: the setor values 1~6 do not correspond to the sectors in sequence ipark(v); Va=v->qs; // Va = Uq Vb=(-0.5) * v->qs + (0.8660254) * v->ds; // Vb = 1/2*(sqrt(3)*Ud - Uq) sqrt(3)/2=0.866 Vc=(-0.5) * v->qs - (0.8660254) * v->ds; // Vc = -1/2*(sqrt(3)Ud + Uq) if(Va>0.0000001) // Determine which sector it belongs to sector=1; // Va>0 then a=1; otherwise a=0 if(Vb>0.0000001) // sector=sector+2; // Vb>0 then b=1; otherwise b=0 if(Vc>0.0000001) // sector=sector+4; // Vc>0 then c=1; otherwise c=0 Va=v->qs; Vb=(-0.5) * v->qs + (0.8660254) * v->ds; Vc=(-0.5) * v->qs - (0.8660254) * v->ds; switch(sector){ case 1: //sector==1 corresponds to sector II t1=Vc; t2=Vb; Tb=(0.25)*(1-t1-t2); Ta=Tb+(0.5)*t1; Tc=Ta+(0.5)*t2; break; case 2: //sector==2 corresponds to sector VI t1=Vb; t2=-Va; Ta=(0.25)*(1-t1-t2); Tc=Ta+(0.5)*t1; Tb=Tc+(0.5)*t2; break; case 3: //sector==3 corresponds to sector I t1=-Vc; t2=Va; Ta=(0.25)*(1-t1-t2); Tb=Ta+(0.5)*t1; Tc=Tb+(0.5)*t2; break; case 4://sector==4 corresponds to sector IV t1=-Va; t2=Vc; Tc=(0.25)*(1-t1-t2); Tb=Tc+(0.5)*t1; Ta=Tb+(0.5)*t2; break; case 5: //sector==5 corresponds to sector III t1=Va; t2=-Vb; Tb=(0.25)*(1-t1-t2); Tc=Tb+(0.5)*t1; Ta=Tc+(0.5)*t2; break; case 6: //sector==6 corresponds to sector V t1=-Vb; t2=-Vc; Tc=(0.25)*(1-t1-t2); Ta=Tc+(0.5)*t1; Tb=Ta+(0.5)*t2; break; default: //Error when sector=0 and sector=7Ta=0.5; Tb=0.5; Tc=0.5; } tmr1=Ta*PRD; tmr2=Tb*PRD; tmr3=Tc*PRD; } void InitEPwm1() { // Configure clockEPwm1Regs.TBCTL.bit.CTRMODE = 0x2; // Increase and decrease counting modeEPwm1Regs.TBPRD = PRD; // Set periodEPwm1Regs.TBCTL.bit.PHSEN = 0x0; // Disable phase load synchronizationEPwm1Regs.TBPHS.half.TBPHS = 0x0000; // Phase initial valueEPwm1Regs.TBCTR = 0x0000; // Count initial valueEPwm1Regs.TBCTL.bit.HSPCLKDIV = 0x1; // TBCLK = SYSCLKOUT / (HSPCLKDIV × CLKDIV) EPwm1Regs.TBCTL.bit.CLKDIV = 0x1; // Configure compare register EPwm1Regs.CMPCTL.bit.SHDWAMODE = 0x0; // Use shadow register EPwm1Regs.CMPCTL.bit.SHDWBMODE = 0x0; EPwm1Regs.CMPCTL.bit.LOADAMODE = 0x0; // Update comparator value when counter value is 0 EPwm1Regs.CMPCTL.bit.LOADBMODE = 0x0; // Set comparator initial value EPwm1Regs.CMPA.half.CMPA = 1875; EPwm1Regs.CMPB = 1875; // Mode setting EPwm1Regs.AQCTLA.bit.ZRO = 0x1; // When it is equal to 0, the output is low EPwm1Regs.AQCTLA.bit.CAU = 0x3; // When the count value = the comparison value, the output is negated EPwm1Regs.AQCTLB.bit.ZRO = 0x2; // When it is equal to 0, the output is high EPwm1Regs.AQCTLB.bit.CBU = 0x3; // When the count value = the comparison value, the output is negated // Configure interrupt EPwm1Regs.ETSEL.bit.INTSEL = 0x1; // When the count value reaches 0, the event is triggered EPwm1Regs.ETSEL.bit.INTEN = 1; // Enable interrupt EPwm1Regs.ETPS.bit.INTPRD = 0x1; // Every time an event occurs, an interrupt is triggered} void InitEPwm2() { EPwm2Regs.TBCTL.bit.CTRMODE = 0x2; EPwm2Regs.TBPRD = PRD; EPwm2Regs.TBCTL.bit.PHSEN = 0x0; EPwm2Regs.TBPHS.half.TBPHS = 0x0000; EPwm2Regs.TBCTR = 0x0000; .bit.SHDWAMODE = 0x0; EPwm2Regs.CMPCTL.bit.SHDWBMODE = 0x0; EPwm2Regs.CMPCTL.bit.LOADAMODE = 0x0; EPwm2Regs.CMPB = 1875; EPwm2Regs.AQCTLA.bit.ZRO = 0x1; EPwm2Regs.AQCTLA.bit.CAU = 0x3; EPwm2Regs.AQCTLB.bit.ZRO = 0x2; //Mask interrupt} void InitEPwm3(void) { EPwm3Regs.TBCTL.bit.CTRMODE = 0x2; EPwm3Regs.TBPRD = PRD; EPwm3Regs.TBCTL.bit.PHSEN = 0x0;
EPwm3Regs.TBPHS.half.TBPHS = 0x0000;
EPwm3Regs.TBCTR = 0x0000;