3.5 正弦波永磁同步电动机驱动控制程序
//########################################################################## #
// 采用矢量控制算法控制永磁同步电机
// TMS320F2812
//########################################################################## #
//=====================================================================
//头文件调用
//=====================================================================
#include "DSP281x_Device.h"
//=====================================================================
//常量附值
//=====================================================================
#define Delta 5
#define PI 3.1415926
#define Kpspeed 0.7 //0.9 //转速环PI调节器低速时参数要大一些
#define Kispeed 0.7 //0.6 // 0.6 0.6 150转时
#define Kpd 0.1 //0.07
#define Kid 0.1 //0.1
#define Kpq 0.15 //0.22 //0.22 //0.07
#define Kiq 0.1 //0.04 //0.04 //0.1
//=====================================================================
//全局变量
//===================================================================== unsigned int index1; //index1为转子位置角用于PARK PARKN变换unsigned int index2;
unsigned int testtime; //index2为转子位置角加或减2分之PI
int charge=0; //自举充电时间控制位
unsigned long rd=0; //转子定位时间控制位
int L2=0; //T2计数器当前计数值
int L1=0; //T2计数器上一次计数值
int L; //计数器两次差值用于M法转速计算
int lin=0;
unsigned int capcount=0;
unsigned int cap[50];
//通过SCI口发信息
unsigned int scienable=0;
unsigned int canchannel=0; //发送选项控制
unsigned long a=0,b=0;
unsigned int speedsci=0;
unsigned int speedsd=0;
unsigned int speedthousand=3; //转速千位
unsigned int speedhundred=3; //转速百位
unsigned int speeddecade=1; //转速十位
unsigned int speedlow=0;
unsigned int Udc=3500; //转速个位
unsigned int Udcthousand=0; //电压千位
unsigned int Udchundred=0; //电压百位
unsigned int Udcdecade=4; //电压十位
unsigned int Udclow=8; //电压个位
unsigned int Idc=0;
unsigned int Idcthousand=0; //电流千位
unsigned int Idchundred=0; //电流百位
unsigned int Idcdecade=6; //电流十位
unsigned int Idclow=0; //电流个位
unsigned int scicount=0; //向上位机发送数据周期控制unsigned long setspeed=2500; //上位机设定的速度
unsigned int scisend[6];
char ReceivedChar=0;
char scired[6];
int p=0,q=0,sciflag=0,tenable=0;
int i,j,t;
//AD数字滤波
unsigned int once=0;
long Ia_now;
long Ia_fore;
long Ib_now;
long Ib_fore;
long Ic_now;
unsigned int ad_count;
unsigned int delay=0;
unsigned int S_Ia=0;
unsigned int ia[18]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; unsigned int ib[18]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long Icb,Ica; //CLARK变换两相静止坐标系电流
long Iat,Ibt; //AD数字滤波中间变量
long Ia=0,Ib=0,Ic=0; //滤波后的电流值
//转速环PI调节参数
int direct=0; //转向控制 0为正转 1为反转
long speed_given=170; //转速给定
long speed_count=10; //转速计算周期控制标志
long speed_feed=0; //转速反馈
long speed_out2=0; //上次转速调节器输出
long speed_e1; //当前转速偏差
long speed_e2=0; //上次转速偏差
//电流环PI调节参数
long Id_given=0; //Id给定
long Iq_given=0; //Iq给定转速调节器输出long Id_feed; //d轴电流反馈值
long Iq_feed; //q轴电流反馈值
long Id_e; //d轴当前电流偏差
long Id_e0=0; //d轴上次电流偏差
long Iq_e; //q轴当前电流偏差
long Iq_e0=0; //q轴上次电流偏差
long Ud=-150; //d轴电流调节器输出
long Uq=1000; //q轴电流调节器输出
long Ud0=0; //上次d轴电流调节器输出long Uq0=0; //上次q轴电流调节器输出long Upa,Upb; //Ud Uq PARKN变换值
long Ua,Ub,Uc; //SPWM调制电压
void init_SCI(void); //串口初始化
void scia_xmit(int a); //串口发送函数
void init_eva(void); //EVA初始化
void init_ADC(void); //ADC初始化
void calcuindex(void); //转子位置角计算
void calcuspeed(void); //转速计算
void speed_PI(void); //转速环PI调节
void AD(void); //AD采样及滤波
void I_PI(void); //电流环PI调节
void CLARK(void); //CLARK变换
void CLARKN(void); //CLARK逆变换
void PARK(void); //PARK变换
void PARKN(void); //PARK逆变换
interrupt void t1pint_isr(void); //定时器1中断服务程序interrupt void cap3_isr(void); //捕获单元3中断服务程序interrupt void sci_isr(void);
signed int sintable[512]=//同SPWM
//Q15格式,将2PI弧度分成了512份
void main(void)
{
//初始化系统
InitSysCtrl();
//关中断
DINT;
IER = 0x0000;
IFR = 0x0000;
//初始化PIE中断
InitPieCtrl();
//初始化PIE中断矢量
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
InitPieVectTable();
EALLOW;
//GpioMuxRegs.GPFMUX.bit.CANTXA_GPIOF6=1;
//GpioMuxRegs.GPFMUX.bit.CANRXA_GPIOF7=1;
GpioMuxRegs.GPAMUX.all = 0x073F; // EVA PWM 1-6 pins GpioMuxRegs.GPBMUX.bit.PWM7_GPIOB0=0; //继电器开关
GpioMuxRegs.GPBDIR.bit.GPIOB0=1;
GpioMuxRegs.GPBMUX.bit.C4TRIP_GPIOB13=0; //LED控制
GpioMuxRegs.GPBDIR.bit.GPIOB13=1;
GpioMuxRegs.GPFMUX.bit. SCITXDA_GPIOF4=1;
GpioMuxRegs.GPFMUX.bit. SCIRXDA_GPIOF5=1;
EDIS;
EALLOW;
PieVectTable.T1UFINT = &t1pint_isr;
PieVectTable.CAPINT3 = &cap3_isr;
PieVectTable.RXAINT=&sci_isr;
EDIS;
EvaRegs.EVAIFRA.all = 0XFFFF;
EvaRegs.EVAIMRA.all = 0X0200;
IER |= M_INT2;
IER |= M_INT3;
IER |= M_INT9;
PieCtrlRegs.PIEIER2.bit.INTx6 = 1;//定时器中断
//PieCtrlRegs.PIEIER3.bit.INTx7 = 1;
PieCtrlRegs.PIEIER9.bit.INTx1 = 1;
EALLOW;
GpioDataRegs.GPBDAT.bit.GPIOB0=0;
EDIS;
//开中断
init_SCI();
init_eva(); //初始化EVA
init_ADC(); //初始化ADC
if(direct==0)
speed_given=speed_given; //正反转速度设定
else
speed_given=-speed_given;
EINT;
ERTM;
for(;;)
{
if((scienable==1)&&(tenable==1)==1)
{
//speedsci=setspeed;
tenable=0;
speedthousand=speedsci/1000;
speedhundred=speedsci/100%10;
speeddecade=speedsci/10%10;
speedlow=speedsci%10;
scisend[0]='s';
scisend[1]=0x30+speedthousand; //speedthousand scisend[2]=0x30+speedhundred; //speedhundred scisend[3]=0x30+speeddecade; //speeddecade
scisend[4]=0x30+speedlow; //speedlow
scisend[5]='p';
while(1)
{
if(SciaRegs.SCICTL2.bit.TXRDY == 1)
{
scia_xmit(scisend[p]);
p++;
}
if(p>5)
{
p=0;
break;
}
}
}
}
}
void init_SCI()
{
// Note: Clocks were turned on to the SCIA peripheral
// in the InitSysCtrl() function
SciaRegs.SCICCR.all =0x0007; // 1 stop bit, No loopback
// No parity,8 char bits,
// async mode, idle-line protocol SciaRegs.SCICTL1.all =0x0003; // enable TX, RX, internal SCICLK,
// Disable RX ERR, SLEEP, TXWAKE SciaRegs.SCICTL2.all =0x0003;
SciaRegs.SCICTL2.bit.TXINTENA =1;
SciaRegs.SCICTL2.bit.RXBKINTENA =1;
SciaRegs.SCIHBAUD =0x0001;
SciaRegs.SCILBAUD =0x00E7;
SciaRegs.SCICCR.bit.LOOPBKENA =0; // disable loop back
SciaRegs.SCICTL1.all =0x0023; // Relinquish SCI from Reset
}
void scia_xmit(int a)
{
SciaRegs.SCITXBUF=a;
}
void init_eva()
{
EvaRegs.T1PR=7500; // Timer1 period
EvaRegs.T1CNT=0x0000; // Timer1 counter
EvaRegs.ACTRA.all=0x0333; //0x033D;
EvaRegs.DBTCONA.all=0x0FFC; //6.4μs的死区
EvaRegs.COMCONA.all=0x8207;
EvaRegs.COMCONA.bit.ACTRLD=2;
EvaRegs.GPTCONA.all=0X0080;
EvaRegs.T1CON.all=0x0842; //连续增减记数模式,定时器时钟1分频
EvaRegs.T2PR=9999; //光电编码器2500线
EvaRegs.T2CON.all=0x1830;
EvaRegs.T2CNT=0;
EvaRegs.CAPCONA.all=0X1404; //使能QEP
}
void init_ADC(void)
{
AdcRegs.ADCTRL1.all=0X1240; /AD内核时钟预定标18.75MHZ,采样窗口3,双排序模式 AdcRegs.ADCTRL1.bit.CONT_RUN=1; //连续运行
AdcRegs.ADCTRL3.bit.ADCCLKPS=3; //AD内核时钟3.125MHz
AdcRegs.ADCTRL2.all=0X4100; //事件管理器A启动SEQ1
AdcRegs.ADCTRL3.bit.ADCBGRFDN=3;
for(i=0;i<1000;i++)
{ ;}
AdcRegs.ADCTRL3.bit.ADCPWDN=1;
for(i=0;i<500;i++)
{ ;}
AdcRegs.ADCMAXCONV.all=0x0001; // Setup 2 conv's on SEQ1
AdcRegs.ADCCHSELSEQ1.bit.CONV00=0; // Setup ADCINA0 as 1st SEQ1 conv. AdcRegs.ADCCHSELSEQ1.bit.CONV01=1; // Setup ADCINA1 as 2nd SEQ1 conv. }
//*******************************************************************//
//根据L正反转4种不同情况进行转速计算所得转速均为正值
//*******************************************************************//
void calcuspeed(void)
{
if((L>=0)&&(L<2000))
speed_feed=L*3;
if((L<0)&&(L<-2000))
speed_feed=(10000+L)*3;
if((L>0)&&(L>2000))
speed_feed=(10000-L)*3;
if((L<0)&&(L>=-2000))
speed_feed=(-L)*3;
if(speed_feed>0)
speedsci=speed_feed;
else
speedsci=-speed_feed;
}
void speed_PI(void)
{
speed_e1=speed_given-speed_feed;
Iq_given=speed_out2+Kpspeed*(speed_e1-speed_e2)+Kispeed*speed_e1;
if(Iq_given>500)
Iq_given=500;
if(Iq_given<-500)
Iq_given=-500;
speed_e2=speed_e1;
speed_out2=Iq_given;
}
//*****************************************************************//
//AD采样及滤波连续采样18次,舍弃最大值和最小值剩下的再取平均值
//*****************************************************************//
void AD(void)
{
for(ad_count=0;ad_count<=17;ad_count++)
{
for(delay=0;delay<=10;delay++)
{}
ia[ad_count]=AdcRegs.ADCRESULT0>>4;
ib[ad_count]=AdcRegs.ADCRESULT1>>4;
}
//testtime=0;
for(j=1;j<=17;j++)
for(i=0;i<=17-j;i++)
{
if(ia[i]>ia[i+1])
{t=ia[i];ia[i]=ia[i+1];ia[i+1]=t;}
if(ib[i]>ib[i+1])
{t=ib[i];ib[i]=ib[i+1];ib[i+1]=t;}
}
EvaRegs.EVAIFRA.all=0XFFFF;
Iat=(ia[5]+ia[6]+ia[7]+ia[8]+ia[9]+ia[10]+ia[11]+ia[12])>>3;
Ibt=(ib[5]+ib[6]+ib[7]+ib[8]+ib[9]+ib[10]+ib[11]+ib[12])>>3;
Ia=Iat-2110;
Ib=Ibt-2110;
if(once==0)
{
Ia_fore=Ia;
Ib_fore=Ib;
once=1;
}
Ia_now=(Delta*Ia+(8-Delta)*Ia_fore)>>3;
Ib_now=(Delta*Ib+(8-Delta)*Ib_fore)>>3;
Ia_fore=Ia_now;
Ib_fore=Ib_now;
Ic_now=-(Ia_now+Ib_now);
}
//******************************************************************// //Ud Uq限幅值限定了最高转速
//******************************************************************// void I_PI(void)
{
Id_e=Id_given-Id_feed; //2*Id_feed
Ud=Ud0+Kpd*(Id_e-Id_e0)+Kid*Id_e;
Iq_e=Iq_given-Iq_feed; //2*Iq_feed
Uq=Uq0+Kpq*(Iq_e-Iq_e0)+Kiq*Iq_e;
if(Ud>500)
Ud=500;
if(Ud<-500)
Ud=-500;
if(Uq>2500)
Uq=2500;
if(Uq<-2500)
Uq=-2500;
Ud0=Ud;
Uq0=Uq;
Id_e0=Id_e;
Iq_e0=Iq_e;
}
void CLARK(void)
{
Ica=(5017*Ia_now)>>12;
Icb=((2896*Ia_now)>>12)+((5793*Ic_now)>>12);
}
void CLARKN(void)
{
Ua=(Upa*3344)>>12;
Ub=((-Upa*1672)>>12)+((Upb*2896)>>12);
Uc=-(Ua+Ub);
if(Ua>7500)
Ua=7500;
if(Ua<-7500)
Ua=-7500;
if(Ub>7500)
Ub=7500;
if(Ub<-7500)
Ub=-7500;
if(Uc>7500)
Uc=7500;
if(Uc<-7500)
Uc=-7500;
}
void PARK(void)
{
Id_feed=((Ica*sintable[index2])>>15)+((Icb*sintable[index1])>>15);
Iq_feed=-((Ica*sintable[index1])>>15)+((Icb*sintable[index2])>>15); }
void PARKN(void)
{
Upa=((Ud*sintable[index2])>>15)-((Uq*sintable[index1])>>15);
Upb=((Ud*sintable[index1])>>15)+((Uq*sintable[index2])>>15);
}
//***********************************************************************// //转子位置角计算由当前T2计数值计算
//***********************************************************************// void calcuindex(void)
{
index1=(210*(long)L2)>>12; //(210*(long)L2)>>10;两对极电机应改为105;
for(i=0;i<4;i++) //一对极 (210*(long)L2)>>12;
{
if(index1>=512)
index1=index1-512;
}
if(index1<=384)
index2=index1+128;
else
index2=index1-384;
}
//=====================================================================
//T1下溢中断子程序
//===================================================================== interrupt void t1pint_isr(void)
{
scicount++; //串口发送周期1秒(5000*200us)
if(scicount==5000)
{
tenable=1;
scicount=0;
}
if(charge!=6000) //自举充电时间1.2秒(6000*200us)
charge++;
else if(rd!=60000) //转子定位时间6秒(30000*200us)
{
EvaRegs.ACTRA.all=0x0999;
Uq=0;
Ud=1300;
index1=0;
index2=128;
PARKN(); //PARK逆变换
CLARKN(); //CLARK逆变换
EvaRegs.CMPR1=3750-(Ua>>1); //装载比较寄存器
EvaRegs.CMPR2=3750-(Ub>>1);
EvaRegs.CMPR3=3750-(Uc>>1);
rd++;
}
else
{
if(lin==0)
{
lin=1;
}
Ud=0;
Uq=setspeed;
L2=EvaRegs.T2CNT;
EvaRegs.T2CON.all=0x1870;
EvaRegs.ACTRA.all = 0x0999; //PWM1-6低有效
if(speed_count==10) //每2毫秒计算一次转速
{
speed_count=0;
L=L2-L1;
calcuspeed();
speed_PI();
L1=L2;
}
speed_count++;
AD();
CLARK(); //CLARK变换
calcuindex(); //计算转子位置角
PARK(); //PARK变换
I_PI();
PARKN(); //PARK逆变换
CLARKN(); //CLARK逆变换
EvaRegs.CMPR1=3750-(Ua>>1); //装载比较寄存器
EvaRegs.CMPR2=3750-(Ub>>1);
EvaRegs.CMPR3=3750-(Uc>>1);
EvaRegs.EVAIMRC.all = 0X0004;
}
EvaRegs.EVAIFRA.all = 0XFFFF;
EvaRegs.EVAIMRA.all = 0X0200;
PieCtrlRegs.PIEACK.all |= PIEACK_GROUP2;
}
//===================================================================== //cap中断子程序
//===================================================================== interrupt void cap3_isr(void)
{
EvaRegs.T2CNT=782; //Z脉冲出现计数器清0
PieCtrlRegs.PIEACK.all |= PIEACK_GROUP3; EvaRegs.EVAIFRC.all = 0XFFFF;
EvaRegs.EVAIMRC.all = 0X0004;
}
//===================================================================== //sci下溢中断子程序
//===================================================================== interrupt void sci_isr(void)
{
ReceivedChar=SciaRegs.SCIRXBUF.all;
ReceivedChar&=0x00FF;
scired[q]=ReceivedChar;
q++;
if(q>5)
{
q=0;
sciflag=1;
}
if(sciflag==1)
{
sciflag=0;
if(scired[1]=='e')//cmd1[6]={"sendsp"}发送转速
//cmd2[6]={"stopsd"}停止发送转速
//cmd[6]={"sp"}速度设定
scienable=1;
else if(scired[1]=='t')
scienable=0;
else
if(scired[1]=='p')setspeed=(scired[2]-0x30)*1000+(scired[3]-0x30)*100+ (scired[4]-0x30)*10+(scired[5]-0x30);
}
SciaRegs.SCIRXST.bit.RXRDY=0;
PieCtrlRegs.PIEACK.all |= PIEACK_GROUP9;
}
//===================================================================== // No more.
//=====================================================================