📄 svpwm.c
字号:
//(2)主程序
//该程序用于简单的SVPWM演示,产生互差120度电角度的正统交流电压,此程序实时计算cmp1和cmp2的值
#include "register.h"
#include "float.h"
#include "math.h"
float ualfa[200],ubeta[200];
int sector[200];
#define PI2 2*3.1415926
#define DETA PI2/200
#define INIA 3.1415926/180
#define TP 1200 //t1的周期寄存器的值,其值等于SVPWM市制周期T的一半,
//因为在该程序中2PI电角度内Uout的点数一定,帮改变此
//值可以改变输出的三相正统交流电压的频率
#define KP 0.7 //定义Uout的标么值,KP的值在0和1之间,改变此值可以改变
//逆变桥输出的电压幅值
//屏蔽中断子程序
void inline disable()
{
asm(" setc INTM");
}
//系统初始化子程序
void initial()
{
SCSR1=0x81FE; // CLKIN=6M,CLKOUT=4*CLKIN=24M
WDCR=0x0E8; // 不使能看门狗,因为SCSR2中的WDOVERRIDE
// 即WDC复位后的缺省值,故可以用
// 软件禁止看门狗
IMR=0x0000; // 禁止所有中断
IFR=0x0FFFF;
T3PR=TP; //通用定时器1的周期=PWM的周期/指令周期/2
T3CON=0X0802; //设置通用定时器1为连续增减模式,以产生对称PWM
//且为了便于高度使仿真一挂起时钟就停止运行
ACTRB=0X666; //PWM7、9、11高有效,PWM8、10、12低有效
COMCONB=0X9200; //
EVBIMRA=0X00;
T3CNT=0X00;
EVBIFRA=0X0FFFF;
MCRC=MCRC|0X7E; //IOPF口和IOPE0口为一般I/O口,
//IOPE其它口为复用PWM功能
WSGR=0X0000; //不使能所有的等待状态
}
//根据Uout的标幺值KP计算ualfa,ubeta子程序
void calu()
{
int i;
for(i=0;i<200;i++)
{
ualfa[i]=KP*cos(INIA+i*DETA);
ubeta[i]=KP*sin(INIA+i*DETA);
}
}
//各点的扇区确定子程序
void SECTOR()
{
int i,a,b,c;
float vref1,vref2,vref3;
for(i=0;i<200;i++)
{
vref1=ubeta[i];
vref2=(-ubeta[i]+ualfa[i]*1.732051)/2;
vref3=(-ubeta[i]-ualfa[i]*1.732051)/2; //计算确定扇区数需要的3个参考量
//vref1,vref2,vref3
if(vref1>0) a=1;
else a=0;
if(vref2>0) b=1;
else b=0;
if(vref3>0) c=1;
else c=0;
a=4*c+2*b+a;
switch(a){
case 1:sector[i]=1;break;
case 2:sector[i]=5;break;
case 3:sector[i]=0;break;
case 4:sector[i]=3;break;
case 5:sector[i]=2;break;
case 6:sector[i]=4;break;
default :break;
} //根据相应的关系确定每个Uout所在的扇区
}
}
//主程序
main()
{
int anticlk[6]={0x1666,0x3666,0x2666,0x6666,0x4666,0x5666};
//逆时针旋转的6个基本矢量
int i,k=0,cmp1,cmp2;
float x,y,z;
disable();
initial();
calu();
SECTOR();
while(1) {
for(i=0;i<200;i++){
ACTRB=anticlk[sector[i]]; //重新装配ACTRA,
x=ubeta[i];
y=(ubeta[i]+ualfa[i]*1.732051)/2;
z=(ubeta[i]-ualfa[i]*1.732051)/2; //以上3句计算相应的参考量
switch(sector[i]){
case 0:cmp1=(int)(-z*TP),cmp2=(int)(x*TP);break;
case 1:cmp1=(int)(y*TP),cmp2=(int)(z*TP);break;
case 2:cmp1=(int)(x*TP),cmp2=(int)(-y*TP);break;
case 3:cmp1=(int)(z*TP),cmp2=(int)(-x*TP);break;
case 4:cmp1=(int)(-y*TP),cmp2=(int)(-z*TP);break;
case 5:cmp1=(int)(-x*TP),cmp2=(int)(y*TP);break;
default:break;
} //以上根据Uout所处的扇区计算相应的cmp1和cmp2
CMPR4=cmp1; //比较寄存器4赋值
CMPR5=cmp2+cmp1; //比较寄存器5赋值
if (i+k==0) T3CON=T3CON|0x040; //启动定时器,且只1次
while(1){
k=EVBIFRA&0x0200;
if(k==0x0200) break; //如果T3的中断标志建立,则停止等待
}
}
}
}
// 如果由于干扰引起的中断,则直接返回中断服务程序
void interrupt nothing( )
{
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -