www.pudn.com > DSP-SVPWM.rar > SV_PWM.c, change:2012-02-15,size:8420b


//***************************************************/ 
//文件名:SVPWM.c 
//功能:调用28335内部PWM模块生成SVPWM输出测试文件 
//说明:输入信息采用结构体,使用时改变结构体指针即可改变输入信号。 
//     InitSvpwm()函数提供PWM模块初始化以及相应PIE中断的配置。 
//     通过park逆变换得到静止平面坐标系下的电压信号。 
//     在PWM定时器下溢中断中更新比较器的值,即每个PWM周期更新一次 
//****************************************************/ 
 
#include "DSP2833x_Device.h"     // DSP2833x Headerfile Include File 
#include "DSP2833x_Examples.h"   // DSP2833x Examples Include File 
#include "math.h" 
#include "float.h" 
 
typedef struct 
{ 
   float ds;              // 静止平面坐标系下电压信号 
   float qs; 
   float ang;             // 电气角度 电气角度=机械角度*极对数 
   float de;              // 旋转坐标系下电压信号 
   float qe; 
}IPARK; 
  IPARK ipark1={0,0,0,0.3,0.4}; 
//  IPARK *v=&ipark1;       //改变此处结构体指针改变输入 
 
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周期寄存器 
#define PI 3.1415926 
float tmr1,tmr2,tmr3; 
 
void main(void) 
{ 
 
/*   InitSysCtrl(); 
 
   DINT; 
 
   InitPieCtrl(); 
 
   IER = 0x0000; 
   IFR = 0x0000; 
 
   InitPieVectTable(); 
*/ 
   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; 
 
// 使能中断 EPWM INT1 位于PIE中断分组3.1 
   PieCtrlRegs.PIEIER3.bit.INTx1 = 1; 
 
   EINT;  
   ERTM; 
} 
 
interrupt void epwm1_isr(void) 
{ 
   // 更新 CMPA 和 CMPB 寄存器值 
   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; 
    
   // 清除中断标志 
   EPwm1Regs.ETCLR.bit.INT = 1; 
 
   // 清除中断响应 
   PieCtrlRegs.PIEACK.all = PIEACK_GROUP3; 
} 
 
 
void ipark(IPARK *v) 
{  
  float  ang; 
  ang=(v->ang/360)*2*PI;                    //角度转化为弧度 
  v->ds=v->de*cos(ang)-v->qe*sin(ang);      //得到静止平面坐标系下d轴电压 
  v->qs=v->qe*cos(ang)+v->de*sin(ang);      //得到静止平面坐标系下q轴电压 
} 
 
void svgen(IPARK *v) 
{ 
   float Va,Vb,Vc,t1,t2,Ta,Tb,Tc; 
   Uint32 sector=0;                                               // sector=a+2b+4c 扇区状态标示 注意:setor的值1~6与扇区不是顺序对应 
   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)                                               // 判断属于哪个扇区         
   sector=1;                                                      // Va>0 则 a=1;否则a=0 
   if(Vb>0.0000001)                                               //  
   sector=sector+2;                                               // Vb>0 则 b=1;否则b=0 
   if(Vc>0.0000001)                                               // 
   sector=sector+4;                                               // Vc>0 则 c=1; 否则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 对应扇区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 对应扇区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 对应扇区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 对应扇区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 对应扇区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 对应扇区V    
       t1=-Vb; 
       t2=-Vc; 
       Tc=(0.25)*(1-t1-t2); 
       Ta=Tc+(0.5)*t1; 
       Tb=Ta+(0.5)*t2; 
       break; 
     default:                             //sector=0和sector=7时错误  
       Ta=0.5; 
       Tb=0.5; 
       Tc=0.5; 
   } 
   tmr1=Ta*PRD; 
   tmr2=Tb*PRD; 
   tmr3=Tc*PRD; 
} 
void InitEPwm1() 
{  
   // 配置时钟 
   EPwm1Regs.TBCTL.bit.CTRMODE = 0x2;             // 增减计数模式 
   EPwm1Regs.TBPRD = PRD;                         // 设置周期 
   EPwm1Regs.TBCTL.bit.PHSEN = 0x0;               // 禁用相位加载同步 
   EPwm1Regs.TBPHS.half.TBPHS = 0x0000;           // 相位初值 
   EPwm1Regs.TBCTR = 0x0000;                      // 计数初值 
   EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0x1;           // TBCLK = SYSCLKOUT / (HSPCLKDIV × CLKDIV) 
   EPwm1Regs.TBCTL.bit.CLKDIV = 0x1; 
 
   // 配置比较寄存器 
   EPwm1Regs.CMPCTL.bit.SHDWAMODE = 0x0;          //使用阴影寄存器        
   EPwm1Regs.CMPCTL.bit.SHDWBMODE = 0x0; 
   EPwm1Regs.CMPCTL.bit.LOADAMODE = 0x0;          //计数器值为0时更新比较器值 
   EPwm1Regs.CMPCTL.bit.LOADBMODE = 0x0; 
 
   // 设置比较器初值 
   EPwm1Regs.CMPA.half.CMPA = 1875;                
   EPwm1Regs.CMPB = 1875;                          
 
   // 模式设定 
   EPwm1Regs.AQCTLA.bit.ZRO = 0x1;               // 等于0时输出低 
   EPwm1Regs.AQCTLA.bit.CAU = 0x3;               // 计数值=比较值时输出取反 
   EPwm1Regs.AQCTLB.bit.ZRO = 0x2;               // 等于0时输出高 
   EPwm1Regs.AQCTLB.bit.CBU = 0x3;               // 计数值=比较值时输出取反 
 
   // 配置中断 
   EPwm1Regs.ETSEL.bit.INTSEL = 0x1;             // 计数值到0触发事件 
   EPwm1Regs.ETSEL.bit.INTEN = 1;                // 使能中断 
   EPwm1Regs.ETPS.bit.INTPRD = 0x1;              // 每次事件发生都触发中断 
} 
 
 
void InitEPwm2() 
{ 
   EPwm2Regs.TBCTL.bit.CTRMODE = 0x2;         
   EPwm2Regs.TBPRD = PRD;                   
   EPwm2Regs.TBCTL.bit.PHSEN = 0x0;           
   EPwm2Regs.TBPHS.half.TBPHS = 0x0000;         
   EPwm2Regs.TBCTR = 0x0000;                   
   EPwm2Regs.TBCTL.bit.HSPCLKDIV = 0x1;      
   EPwm2Regs.TBCTL.bit.CLKDIV = 0x1; 
   EPwm2Regs.CMPCTL.bit.SHDWAMODE = 0x0;           
   EPwm2Regs.CMPCTL.bit.SHDWBMODE = 0x0; 
   EPwm2Regs.CMPCTL.bit.LOADAMODE = 0x0;     
   EPwm2Regs.CMPCTL.bit.LOADBMODE = 0x0; 
   EPwm2Regs.CMPA.half.CMPA = 1875;                
   EPwm2Regs.CMPB = 1875;                          
   EPwm2Regs.AQCTLA.bit.ZRO = 0x1;                         
   EPwm2Regs.AQCTLA.bit.CAU = 0x3;                 
   EPwm2Regs.AQCTLB.bit.ZRO = 0x2;              
   EPwm2Regs.AQCTLB.bit.CBU = 0x3;                      
   EPwm2Regs.ETSEL.bit.INTEN = 0;                 //屏蔽中断              
             
} 
 
void InitEPwm3(void) 
{ 
   EPwm3Regs.TBCTL.bit.CTRMODE = 0x2;           
   EPwm3Regs.TBPRD = PRD;                       
   EPwm3Regs.TBCTL.bit.PHSEN = 0x0;              
   EPwm3Regs.TBPHS.half.TBPHS = 0x0000;         
   EPwm3Regs.TBCTR = 0x0000;                     
   EPwm3Regs.TBCTL.bit.HSPCLKDIV = 0x1;            
   EPwm3Regs.TBCTL.bit.CLKDIV = 0x1; 
   EPwm3Regs.CMPCTL.bit.SHDWAMODE = 0x0;                 
   EPwm3Regs.CMPCTL.bit.SHDWBMODE = 0x0; 
   EPwm3Regs.CMPCTL.bit.LOADAMODE = 0x0;           
   EPwm3Regs.CMPCTL.bit.LOADBMODE = 0x0; 
   EPwm3Regs.CMPA.half.CMPA = 1875;                
   EPwm3Regs.CMPB = 1875;                          
   EPwm3Regs.AQCTLA.bit.ZRO = 0x1;                 
   EPwm3Regs.AQCTLA.bit.CAU = 0x3;                  
   EPwm3Regs.AQCTLB.bit.ZRO = 0x2;                  
   EPwm3Regs.AQCTLB.bit.CBU = 0x3;                      
   EPwm3Regs.ETSEL.bit.INTEN = 0;                            
}