⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 svpwm.c

📁 直流无刷电机控制程序
💻 C
字号:
// 该程序用于简单的SVPWM演示,产生3相互差120度电角度的正弦交流电压,此程序实
// 时计算cmp1和cmp2的值 
#include 		<regs240x.h> 
//#include 		"float.h" 
//#include 		"math.h"
float			ualfa[200],ubeta[200]; // 存储电压矢量Uout的(α,β)轴分量ualfa、ubeta的数组 
int			sector[200];		  // 定义存储扇区数的数组 
#define	 	PI2		2*3.1415926   // 定义2π的值   
#define	 	DETA	PI2/200       // 定义相临两个Uout之间的电角度的差值 
#define	 	INIA		3.1415926/180  // 定义Uout的初始电角度  
#define	 	TP       1200   	  // t1的周期寄存器的值,其值等于SVPWM调制周期T的一半,
			            		  // 因为在该程序中2π电角度内Uout的点数一定,故改变此值
                         		  // 可以改变输出的3相正弦交流电压的频率 
#define	 	KP      0.7      	  // 定义Uout的标幺值,KP的值在0和1之间,改变此值可以
			             		  // 改变逆变桥输出电压的幅值 
//  屏蔽中断子程序         
void inline disable() 
{
	asm(" setc INTM");
}
// 系统初始化子程序 
viod  initial()
{
	*IFR=0xFFFF;				     //  清除所有的中断标志    	
	*IMR=0X0;  			     	// 屏蔽所有中断 
	*SCSR1=0x81FE;  				// CLKIN=6M,CLKOUT=24M 
    	*WDCR=0xE8;     				// 不使能看门狗 
	*T3PER=TP;					// 通用定时器1的周期=PWM的周期/指令周期/2 
	*T3CON=0X0802;				// 设置通用定时器1为连续增减模式,以产生对称的PWM,
		           				// 且为了便于调试,使仿真一挂起时时钟就停止运行 
	*ACTRB=0X666;				// PWM7、9、11高有效,PWM8、10、12低有效 
	*COMCONB=0X9200;			// 使能PWM输出和比较动作 
     *EVBIMRA=0X00;				// 禁止EVB和时钟及比较有关的中断 
	*T3CNT=0X00;				// T1的计数器清0  
	*EVBIFRA=0x0FFFF;			// 清除EVB相应的中断标志  
	*MCRC=*MCRC|0X7E;			// PWM7-PWM12输出使能,使能IOPE1-IOPE6第二功能   	
 	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();							// 计算ualfa,ubeta的值 
	SECTOR();						// 确定各点的扇区,在实际应用时应该由即时
// 的ualfa和ubeta即时算出 
while(1)	{
		for(i=0;i<200;i++)	{
			*ACTRB=anticlk[sector[i]];		// 重新装配ACTRA 
			x=ubeta[i];
			y=(1.732051*ualfa[i]+ubeta[i])/2;
			z=(-1.732051*ualfa[i]+ubeta[i])/2;	// 以上3句计算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=cmp1+cmp2;		// 比较寄存器5赋值 
			if((i+k)==0)		*T3CON=*T3CON|0X040;	// 启动定时器,只启动一次 
while(1)	{
				k=*EVBIFRA&0X0200;
				if(k==0x0200)	break;	// 如果T3的中断标志建立,则停止等待 
			}	
}
}
}
// 如果由于干扰引起中断,则执行此直接返回程序
void interrupt nothing() 
{
	return;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -