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

📄 svpwm.txt

📁 使用TI TMS2407 实现SVPWM同步电机控制算法。源代码在闻廷科技的2407开发板上已经调试成功。
💻 TXT
字号:
#include "register.h"
#define  Fs  2                        //Fs为采样频率kHz(载波频率)

#define PI 180 
const int csin[180]={0,                   //查表法计算正弦值
174,
348, 
523, 
697, 
871, 
1045,  
1218, 
1391, 
1564, 
1736, 
1908, 
2079, 
2249, 
2419, 
2588, 
2756,
2923, 
3090, 
3255, 
3420, 
3583, 
3746, 
3907, 
4067, 
4226, 
4383, 
4539, 
4694, 
4848, 
5000, 
5150, 
5299, 
5446, 
5591, 
5735, 
5877, 
6018, 
6156, 
6293, 
6427, 
6560, 
6691, 
6819, 
6946, 
7071, 
7193, 
7313, 
7431, 
7547, 
7660, 
7771, 
7880, 
7986, 
8090, 
8191, 
8290, 
8386, 
8480, 
8571, 
8660, 
8746, 
8829, 
8910, 
8987, 
9063, 
9135, 
9205, 
9271, 
9335, 
9396, 
9455, 
9510, 
9563, 
9612, 
9659, 
9702, 
9743, 
9781, 
9816, 
9848, 
9876, 
9902, 
9925, 
9945, 
9961, 
9975, 
9986, 
9993, 
9998, 
10000,
9998, 
9993, 
9986, 
9975, 
9961, 
9945, 
9925, 
9902, 
9876, 
9848, 
9816, 
9781, 
9743, 
9702, 
9659, 
9612, 
9563, 
9510, 
9455, 
9396, 
9335, 
9271, 
9205, 
9135, 
9063, 
8987, 
8910, 
8829, 
8746, 
8660, 
8571, 
8480, 
8386, 
8290, 
8191, 
8090, 
7986, 
7880, 
7771, 
7660, 
7547, 
7431, 
7313, 
7193, 
7071, 
6946, 
6819, 
6691, 
6560, 
6427, 
6293, 
6156, 
6018, 
5877, 
5735, 
5591, 
5446, 
5299, 
5150, 
5000, 
4848, 
4694, 
4539, 
4383, 
4226, 
4067, 
3907, 
3746, 
3583, 
3420, 
3255, 
3090, 
2923, 
2756, 
2588, 
2419, 
2249, 
2079, 
1908, 
1736, 
1564, 
1391, 
1218, 
1045, 
871,
697, 
523, 
348, 
174, 
};                                        //存储sin函数的91个单元,每
个单元存递增一度的sin值,放大了100000倍;
unsigned int i=0,j=0;
unsigned long int k=0,t=0,N=0,M=9;          //M值的大小和Fc有关系, Ud
不变,Uc随着Fc的改变而改变,
所以M=Uc/Us值改变。
unsigned long int tm1=0,tm2=0,tm3=0;
unsigned int ADAcount=0,ischange=0,result=0,Fc=25; 

void initial(void);
void sysinit(void);
void intinit(void);
void evainit(void);
void ADInit(void);
void interrupt gptime1(void);
void interrupt nothing(void);
unsigned long int gettime(unsigned long int);

main()
{   
    initial();                               //系统初始化
	sysinit();
	intinit(); 
	ADInit();
    evainit();
    N=1000*Fs/Fc;
   	while(1)
    {
		if ( ADAcount>=200 )	               // 如果ADAcount>=200,以下
开始转换和保存转换结果 
		{
			ADAcount=0;		               //清保存标志 
	     	result=(*RESULT0);                //取ADCINT0通道转换结果 
	     	result>>=6;                       //取有效位
	     	if(result!=0)
	     	{
	     		Fc=result*50/1024;             //将采进的电压值Uc转换为频率Fc
	     		if(Fc<=2)
	     			Fc=2;
	            M=10*Fc/50;  
	   			if(M<=1)
	   				M=1;
	   			if(M>=10)
	   				M=10;
	   			ischange=1;
	   		}
	   	 	*ADCTRL2= 0x2000;
		}
	}
}

void initial(void)
{
	 asm(" setc INTM");                  //禁止中断
     asm(" clrc SXM");                   //清标志位
     asm(" clrc OVM");		           	//OVM清零,累加器中结果正常溢出
     asm(" clrc CNF");                   //CNF清零,B0被设置为数据存储区
}

void sysinit(void)    
{
	 *WDCR=0x68 ;                    //看门狗定时控制寄存器
     *SCSR1=0x81fe;                   //系统控制及状态寄存器1,CPU时
钟频率设置,设为40MHZ
	 *XINT1CR=*XINT2CR=0x8006;      //禁止外部中断
     //*WSGR=0x0000;                  //设置外部存储器的接口
}

void intinit(void)
{
	          
     *IFR=0x003f;                       //清所有系统中断标志
	 *IMR=0x0002;                       //开 INT2  中断   
	
	 *EVAIFRA=0xffff;                 	 //清事件管理器A所有中断标志 
	 *EVAIFRB=0xffff;                  	 //清事件管理器A所有中断标志 
	 *EVAIFRC=0xffff;	                  //清事件管理器A所有中断标志 
     *EVAIMRA=0x0200;	               //T1下溢中断  使能T1PINT 
	 *EVAIMRB=0;	                      //屏蔽所有中断
	 *EVAIMRC=0;                     	 //屏蔽所有中断
}

void evainit(void)
{
     
     *MCRA=*MCRA|0X0fc0;             //设置PWM1~6引脚
	 *ACTRA=0X0999;                    //引脚PWM1、3、5低有效,
PWM2、4、6高有效。
	 *T1PR=10000;                        //T1周期寄存器 值为10000
	 *CMPR1=10000;                      //比较器的比较值,开始为10000,展空比0
	 *CMPR2=10000;
	 *CMPR3=10000;
     *T1CNT=0;                           //定时器1计数寄存器   
	 *DBTCONA=0X08f4;                   //死区周期值为8,是能比较单元1、2、3
的死区操作;死区预分频系数为32,死区
值为7×32=224个CPU时钟周期,CPU时钟周期为50ns,定时器周期为7×32×25ns 
     *COMCONA=0X8200;                 //比较控制寄存器A 允许比较,下溢重载
	 *T1CON=0x0842;                  //定时器1控制寄存器 F=1,连续增减计数方式
     asm(" clrc INTM");                     //开总中断                               
}

void ADInit(void)                            //初始化设置
{
	*ADCTRL1= 0x0900;	                  //设置连续转换模式
	*MAXCONV = 0x0;		                  //每次完成转换1个通道
	*CHSELSEQ1=0x0;	                      // ADCIN0
	*ADCTRL2= 0x2000;                 	//启动转换 
}

void interrupt nothing(void)
{
  asm(" clrc INTM");                           //开总中断
  return;
  }                               
     

void interrupt gptime1(void)
{
	if(k>=N){                            //如果完成了一个完整的正弦脉冲的转换,
重新开始转换一个新的脉冲,从0度开始
		k=0; 
		if(ischange=1){                    //如果ischange被置1,重新计算载波比N
			N=1000*Fs/Fc; 
			ischange=0;
		}                             
	}
	t=k*360/N;                             //计算采样时间点tp的角度
   	tm1=gettime(t%360);                     //计算第一相的开启时间ton
	tm2=gettime((t+120)%360);                //计算第二相的开启时间
	tm3=gettime((t+240)%360);                //计算第三相的开启时间
	k++;                                   //用来计算下一个开启时间点
	ADAcount++;                           //计到200,ADC重新采样,计算给定的
                       正弦调制波的频率 
	if(tm1<80)                              //消除窄脉冲
		tm1=0;
	if(tm1>19920)
		tm1=20000;
	*CMPR1=(20000-tm1)/2;               //将开启时间赋给比较寄存器

	if(tm2<80)
		tm2=0;	
	if(tm2>19920)
		tm2=20000; 
	*CMPR2=(20000-tm2)/2; 
	if(tm3<80)
		tm3=0;
	if(tm3>19920)
		tm3=20000;
	*CMPR3=(20000-tm3)/2;

	*EVAIFRA=0xffff;	                    // 清事件管理器A所有中断标志 
	asm(" clrc INTM");                      //开总中断 
}

unsigned long int gettime(unsigned long int angle)
{                                            //计算开启时间
	unsigned long int num=0;
	if (angle>=180)
		num=(100000-M*csin[angle-180])/Fs/5;     //其中/5是为了除去放大做法的影响,
包括 sin值放大和计时放大。
	else
		num=(100000+M*csin[angle])/Fs/5; 
	if(num>=20000)
		num=20000;
	if(num<=0)
		num=0;
	return num;
}

⌨️ 快捷键说明

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