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

📄 fft.c

📁 2007年全国大学生电子设计大赛
💻 C
字号:
#include<c8051f120.h>
#include<fft.h>
#include"math.h"
#include"math.h"

/*完成日期:5.14
/*修改日期:
/*入口参数:
  X[]:需要变换的数据.变换后放回源数据区域,必须为符号
  FFT_N:FFT点数.
  RealFlag:实数变换的标志.如果为实数,由于处理安复数格式处理.需要变换,此标志控制变换与否.
  //Int16Flag:输入数据为16位满刻度的标志.如果是满刻度的十六位数据.需要先右移一位,否则将溢出.
  SignFlag:输入数据为有符号数据的标志,如果不是有符号数据,需要转换为有符号数据.
*/
/*一定要注意输出数据为有符号数据,所以如果显示处理后得数据要小心,
*/
void Int_FFT(int X[],unsigned int FFT_N,char windowtype,char RealFlag,char SignFlag)
{idata int  DotDiv=2048/FFT_N;  //由于查的表是的角度步进为2*pi/2048;故如果FFT点数少于2048时应查的表的步进要加倍.
 idata int  FFT_HFNum;        //FFT点数 
 idata int  FFT_Level=0;    //FFT的级数 
 idata int  LCnt;         //级数的计数器 
 idata int  FFT_Seg;        //当前级FFT中的段数 
 idata int  SCnt;           //段数计数器 
 idata int  SeGBTF;         //每段包含的碟形算子的个数 
 idata int  ButterFlySCnt;  //每段中碟形算子序号 
 idata int  ButterFlyCnt;	//碟形算子总的序号地址 
 idata int  ButterFlyCpl;   //碟形算子对的另外一个数据的地址 
 idata int  Ele_Inteval;    //每个碟形算子涉及的两个元素的间隔 
// idata int  RealDirCrt,ImagDirCrt;
 #if MAC120
 idata int  Rx1buff,Rx2buff,Ix1buff,Ix2buff;
 idata int  RSxbuff,ISxbuff;
 idata char SFRPAGBUFF;

 #else
 idata long  Rx1buff,Rx2buff,Ix1buff,Ix2buff;
 idata long  RSxbuff,ISxbuff;
 idata long  MACBUF,MACBUF1,MACBUF2,MACBUF3;
 #endif

 idata int  Wnk;
 idata int  WnkInterval;//
 idata int  EXP2[16]={0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,
                      0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000,
                     };//2的N次幂表.
 /*120MCU时的页寄存器处理:
 */
 #if MAC120
 SFRPAGBUFF=SFRPAGE;
 SFRPAGE=MAC0_PAGE;
 #endif
 /*FFT前期数据准备工作.
 */
 if(SignFlag!=1)//如果为不是有符合数据,需要转化为有符合数据.
 	for(LCnt=0;LCnt<FFT_N;LCnt++)
	   {FFT_Seg=X[LCnt];
	    SCnt=FFT_Seg-0x8000;
	    X[LCnt]=SCnt;
	   }
 FFT_N=FFT_N/2;    //用N/2点求,是标准FFT数据量的1/2
 FFT_HFNum=FFT_N;
 FFT_Level=0;
 for(;FFT_N!=0x0001;FFT_N=FFT_N>>1)FFT_Level++; //得到FFT级数 


 /*FFT加窗;
 */
#if MAC120
 MAC0CF=0x01; //工作为乘法方式;
#endif	
 switch(windowtype)
 	   {
	    case 'h':if(RealFlag)
		           {
				    for(LCnt=0,SCnt=0;SCnt<FFT_HFNum*2;LCnt=LCnt+DotDiv)
				       {RSxbuff=X[SCnt];
					    #if MAC120
				 			MAC0A=hammingwindow[LCnt];
						    MAC0B=RSxbuff;
							X[SCnt]=MACW1;
						#else
						//	MACBUF1=hammingwindow[LCnt];
							MACBUF=MACBUF1*RSxbuff;
							MACBUF=MACBUF>>16;
							X[SCnt]=MACBUF;
						#endif
						 	SCnt++;
					   }
				   }
				 break;
	    case 't':break;
	   }
 //if(Int16FullFlag)for(LCnt=0;LCnt<FFT_N;LCnt++)X[LCnt]=X[LCnt]>>1;//如果输入为16位满刻度数据,需要转换为15位以防溢出.

 /*FFT碟形运算:
 */		/*
#if MAC120

#else
 Rx1buff=0;
 Rx2buff=0;
 RSxbuff=0;
 for(LCnt=0;LCnt<FFT_HFNum*2;LCnt++)
 	{Rx1buff=X[LCnt];
	 RSxbuff= RSxbuff+Rx1buff;
	}
 
#endif*/
 /*****遍历所有级***********/
 //DIF算法
 for(LCnt=0;LCnt<FFT_Level;LCnt++)	 //一共要计算的级数 
 	{FFT_Seg=EXP2[LCnt];     //得到本级FFT需要计算的段数 
	 SeGBTF=EXP2[FFT_Level-LCnt-1];//得到本级FFT中每段的算子个数 

	 Ele_Inteval=EXP2[FFT_Level-LCnt];//得到每个碟形算子涉及的两个元素的距离*2 
	 ButterFlyCnt=0;   //碟形算子序号复位

    #if MAC120
	 MAC0CF=0x01;      //工作于乘法方式,不是乘加方式 
	 MAC0A=FFT_Seg;
	 MAC0B=2;
	 MAC0A=DotDiv;
	 MAC0B=MACW0;
	 WnkInterval=MACW0;//得到旋转因子的旋转间隔.WnkInterval=2*FFT_Seg*DotDiv;2是由于实数FFT时将N个点的FFT减少为N/2个点的FFT
  					   //当FFT点数少于2048时步进为2048时的DotDiv(2048/FFT_N)倍.
	 MAC0CF=0x00;	                   //工作于乘加方式,
	#else
	 WnkInterval=FFT_Seg*DotDiv;
	 WnkInterval=WnkInterval<<1;
	#endif
	 /*****遍历本级的所有段***********/
	 for(SCnt=0;SCnt<FFT_Seg;SCnt++)//本级FFT一共要计算的段数 
	 	{
	     Wnk=0;//复位旋转因子;

		 /*****遍历本段的所有碟形算子***********/
		 for(ButterFlySCnt=0;ButterFlySCnt<SeGBTF;ButterFlyCnt=ButterFlyCnt+2)//ButterFlySCnt++在循环体中.
			{ButterFlyCpl=ButterFlyCnt+Ele_Inteval;//

			 Rx1buff=X[ButterFlyCnt];
			 Rx1buff=Rx1buff>>1;
			 Ix1buff=X[ButterFlyCnt+1];
			 Ix1buff=Ix1buff>>1;
			 Rx2buff=X[ButterFlyCpl];
			 Rx2buff=Rx2buff>>1;
			 Ix2buff=X[ButterFlyCpl+1];
			 Ix2buff=Ix2buff>>1;			  //以上为缓存源数据.每一级除以2防止溢出;


			 X[ButterFlyCnt]=Rx1buff+Rx2buff;  //得到实部,这句可以一方面延时以提供MAC需要的时钟周期;
			 X[ButterFlyCnt+1]=Ix1buff+Ix2buff;//得到虚部,碟形算子的 A+B

			 RSxbuff=Rx1buff-Rx2buff;		   //碟形算子的(A-B)WnK;
			 RSxbuff=RSxbuff<<1;
			 ISxbuff=Ix1buff-Ix2buff;
			 ISxbuff=ISxbuff<<1;

			#if MAC120 //如果MCU有硬件MAC则相应用MAC处理 
			 MACW1=0;
			 MACW0=0;
			 MAC0A=RSxbuff;
			 MAC0B=WnC[Wnk];				   //Re(A-B)*Cos(a);
			 MAC0A=ISxbuff;			           //Im(A-B)*Sin(a);
			 MAC0B=WnS[Wnk];
			 X[ButterFlyCpl]=MACW1;			   //由于正弦余弦表扩大了2^15倍.直接读入高16为.


			 MACW1=0;						   //得到Im(A-B)*Cos(a)-Re(A-B)*Sin(a)
			 MACW0=0;
			 MAC0A=~RSxbuff+1;
			 MAC0B=WnS[Wnk];
			 MAC0A=ISxbuff;
			 MAC0B=WnC[Wnk]; 
			 X[ButterFlyCpl+1]=MACW1;		 

		    #else
			 MACBUF=WnC[Wnk];				  //得到Re(A-B)*Cos(a)+Im(A-B)*Sin(a)
			 MACBUF1=MACBUF*RSxbuff;

			 MACBUF=WnS[Wnk];
			 MACBUF2=MACBUF*ISxbuff;

			 MACBUF=MACBUF1+MACBUF2;
			 MACBUF=MACBUF>>16;
			 X[ButterFlyCpl]=MACBUF;

			 MACBUF2=~RSxbuff+1;		      //得到Im(A-B)*Cos(a)-Re(A-B)*Sin(a)
			 MACBUF=WnS[Wnk];
			 MACBUF1=MACBUF*MACBUF2;

			 MACBUF=WnC[Wnk]; 
			 MACBUF2=ISxbuff*MACBUF; 

			 MACBUF=MACBUF1+MACBUF2;
			 MACBUF=MACBUF>>16;
			 X[ButterFlyCpl+1]=MACBUF;		  

		    #endif
			 ButterFlySCnt++;
			 Wnk=Wnk+WnkInterval;			  //旋转因子旋转相应角度.
			}
		ButterFlyCnt=ButterFlyCnt+SeGBTF*2;
		}

	}


 /*********以下程序将倒位序的数据顺序排列*********/
 //借用了变量LCnt,ButterFlySCnt,SCnt
 
 LCnt=10-FFT_Level;
 for(ButterFlySCnt=0;ButterFlySCnt<FFT_HFNum;ButterFlySCnt++)
    {FFT_Seg=BitReversedTable1[ButterFlySCnt];
	 FFT_Seg=FFT_Seg>>LCnt;	    //比1024点小的倒位序表可由词表直接右移LCnt位得到.
	 if(FFT_Seg>ButterFlySCnt)	//保证只交换一次 
		 {
		  SCnt=2*FFT_Seg;//得到要与他相交换的元素序号的地址.
		  Rx1buff=X[SCnt];
	 	  Ix1buff=X[SCnt+1];
	 	  X[SCnt]=X[2*ButterFlySCnt];
	 	  X[SCnt+1]=X[2*ButterFlySCnt+1];
	 	  X[2*ButterFlySCnt]=Rx1buff;
	 	  X[2*ButterFlySCnt+1]=Ix1buff;
		 }
	 }
	 
 /*由于用N/2点计算N点FFT,这里由X[K]=X1[K]+W2nK*X2[k]恢复前N/2个点的值.*/
 /*由于用N/2点计算N点FFT,这里由X[K]=X1[K]+W2nK*X2[k]恢复前N/2个点的值.*/
 /*X1[K]=0.5*[Y(k)+Y~(N-K)]*/
 /*X2[K]=-0.5*j*[Y(K)-Y~(N -K)]*/
 /*得到X[K]=0.5*[Y(K)+Y~(N-K)]-0.5*j*W2nK*[Y(K)-Y~(N-K)]*/
 /*得到X[N-K]=0.5*[Y(N-K)+Y~(K)]-0.5*j*W2n(N-K)*[Y(N-K)-Y~(K)]*/
 /*只计算前N/2个FFT的值,后N/2是镜频.*/
 if(RealFlag)//如果是实数运算则要作以下变换
 	{ButterFlyCpl=FFT_HFNum*2;
	#if MAC120
	 MAC0CF=0x00;
	#endif
	 Rx1buff=X[0];
	 Ix1buff=X[1];
	 Rx1buff=Rx1buff>>1;
	 Ix1buff=Ix1buff>>1;
	 X[0]=Rx1buff+Ix1buff;
	 X[1]=0;
	 WnkInterval=1024/FFT_HFNum;
	 Wnk=WnkInterval;
     for(ButterFlySCnt=2;ButterFlySCnt<FFT_HFNum;ButterFlySCnt=ButterFlySCnt+2,Wnk=Wnk+WnkInterval)/*由于X[K]和X[N-k]配对处理,故计算FFT_HFNum/2次.*/
 		{Rx1buff=X[ButterFlySCnt]; 
	 	 Ix1buff=X[ButterFlySCnt+1];

	 	 Rx2buff=X[ButterFlyCpl-ButterFlySCnt];
	 	 Ix2buff=X[ButterFlyCpl-ButterFlySCnt+1];



 	 	 RSxbuff=Rx1buff+Rx2buff;
 	 	 ISxbuff=Ix1buff+Ix2buff;


	    #if MAC120
	 	 MACW1=0;
	 	 MACW0=0;
	 	 MAC0A=WnC[Wnk];
	 	 MAC0B=ISxbuff;
	 	 MAC0A=WnS[Wnk];
	 	 MAC0B=Rx2buff-Rx1buff;	
		  
		 FFT_Seg= RSxbuff;
		 FFT_Seg=FFT_Seg>>1;
	 	 X[ButterFlySCnt]=FFT_Seg+MACW1;//化简为:Rx1+Rx2+W2nC[k]*(Ix1+Ix2)+W2nS[k]*(Rx2-Rx1)得到实部.

	 	 MACW1=0;
	 	 MACW0=0;
	 	 MAC0A=WnC[Wnk];
	 	 MAC0B=Rx2buff-Rx1buff;
	 	 MAC0A=WnS[Wnk];
	 	 MAC0B=~(ISxbuff)+1;

		 FFT_Seg=Ix1buff-Ix2buff;
		 FFT_Seg=FFT_Seg>>1;
	 	 X[ButterFlySCnt+1]=FFT_Seg+MACW1; //化简为:Ix1-Ix2+W2nC[k]*(Rx2-Rx1)-W2nS[k]*(Ix1+Ix2)得到虚部.
	                             /*以上为得到X[K]的值.*/


	 	 MACW1=0;
	 	 MACW0=0;
		 MAC0A=WnC[1024-Wnk];
		 MAC0B=ISxbuff;
		 MAC0A=WnS[1024-Wnk];
		 MAC0B=Rx1buff-Rx2buff;

		 FFT_Seg= RSxbuff;
		 FFT_Seg=FFT_Seg>>1;
    	 X[ButterFlyCpl-ButterFlySCnt]=FFT_Seg+MACW1;//化简为:Rx1+Rx2+W2n[N-k]*(Ix1+Ix2)+W2nS[k]*(Rx1-Rx2)得到实部.

		 MACW1=0;
		 MACW0=0;
		 MAC0A=WnC[1024-Wnk];
		 MAC0B=Rx1buff-Rx2buff;
		 MAC0A=WnS[1024-Wnk];
		 MAC0B=~(ISxbuff)+1;

		 FFT_Seg= Ix2buff-Ix1buff;
		 FFT_Seg=FFT_Seg>>1;
    	 X[ButterFlyCpl-ButterFlySCnt+1]=FFT_Seg+MACW1;//化简为:Ix2-Ix1+W2nC[N-k]*(Rx1-Rx2)-W2nS[N-k]*(Ix1+Ix2)得到虚部.
		#else
		 MACBUF1=WnC[Wnk];
		 MACBUF2=ISxbuff;
		 MACBUF=MACBUF1*MACBUF2;

		 MACBUF1=WnS[Wnk];
		 MACBUF2=Rx2buff-Rx1buff;

		 MACBUF=MACBUF+MACBUF1*MACBUF2;
		 MACBUF=MACBUF>>16;

		 MACBUF3=RSxbuff;
		 MACBUF3=MACBUF3>>1;
		 MACBUF=MACBUF+MACBUF3;		
         X[ButterFlySCnt]=MACBUF;   //

		 MACBUF1=WnC[Wnk];
		 MACBUF2=Rx2buff-Rx1buff;
		 MACBUF=MACBUF1*MACBUF2;   

		 MACBUF1=WnS[Wnk];
		 MACBUF2=~(ISxbuff)+1;

		 MACBUF=MACBUF+MACBUF1*MACBUF2;
		 MACBUF=MACBUF>>16;

		 MACBUF3=Ix1buff-Ix2buff;
		 MACBUF3=MACBUF3>>1;
		 MACBUF=MACBUF+MACBUF3;
         X[ButterFlySCnt+1]=MACBUF;   //

		 MACBUF1=WnC[1024-Wnk];
		 MACBUF2=ISxbuff;
		 MACBUF=MACBUF1*MACBUF2;

		 MACBUF1=WnS[Wnk];
		 MACBUF2=Rx1buff-Rx2buff;

		 MACBUF=MACBUF+MACBUF1*MACBUF2;
		 MACBUF=MACBUF>>16;

		 MACBUF3=RSxbuff;
		 MACBUF3=MACBUF3>>1;
		 MACBUF=MACBUF+MACBUF3;		
         X[ButterFlyCpl-ButterFlySCnt]=MACBUF;   //

		 MACBUF1=WnC[1024-Wnk];
		 MACBUF2=Rx1buff-Rx2buff;
		 MACBUF=MACBUF1*MACBUF2;

		 MACBUF1=WnS[Wnk];
		 MACBUF2=~(ISxbuff)+1;

		 MACBUF=MACBUF+MACBUF1*MACBUF2;
		 MACBUF=MACBUF>>16;

		 MACBUF3=Ix2buff-Ix1buff;
		 MACBUF3=MACBUF3>>1;
		 MACBUF=MACBUF+MACBUF3;		
         X[ButterFlyCpl-ButterFlySCnt+1]=MACBUF;   //
		#endif
		}
	}

#if MAC120
 SFRPAGE=SFRPAGBUFF;
#endif
}

/*void shizhd(void)
{
 float val1=0,val2=0;
 unsigned int j;
 long int tempval=0,temp1=0,temp2=0;
 SFRPAGE=MAC0_PAGE;
   MAC0CF=0x00;	                   //工作于乘加方式,
 for(j=8;j<256;j=j+16)
 {
   
   MACW1=0;
   MACW0=0;
   MAC0A=source[j];
   MAC0B=source[j];				 
   MAC0A=source[j+1];			           
   MAC0B=source[j+1];
   tempval=MACW1;
   tempval=tempval<<16;
   tempval=tempval+MACW0;
 
  if(j>8)
  {
   temp1=temp1+tempval;
   
  }
  else
  {
   temp2=tempval;
  }
 }

 r1=(float)temp1/temp2;
 r1=sqrt(r1);

}  */

⌨️ 快捷键说明

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