[资料分享] 分享一个DSP28335的SVPWM程序源码,可供参考

fish001   2018-11-10 18:59 楼主
//功能:调用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"
        extern Uint16 RamfuncsRunStart;
        extern Uint16 RamfuncsLoadStart;
        extern Uint16 RamfuncsLoadEnd;
        
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();


        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;


// 使能中断 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;                    
……………………

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复