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

📄 fft_new_test.c

📁 在c8051平台上实现的FFT运算
💻 C
📖 第 1 页 / 共 2 页
字号:
        数组BRTable[]被用来查找哪个值要被交换,只有一半的值被存储在数组中,另一半通过镜像前一半
		得到。
=================================================================================================*/
void BitReverse(int BR_Array[])
{
#if(NUM_FFT>=512)
  unsigned int swapA,swapB,sw_cnt;
#endif

#if(NUM_FFT<=256)
  unsigned char swapA,swapB,sw_cnt;
#endif

  int TempStore;
  for(sw_cnt=1;sw_cnt<NUM_FFT/2;sw_cnt++)//第一部分的交换
  {
    swapA=sw_cnt;                        //保存当前位置
    swapB=BRTable[sw_cnt]*2;             //找到位反向索引
    if(swapB>swapA)                      //如果位反向索引值比当前值大则交换
    {                                   
       TempStore=BR_Array[swapA];
       BR_Array[swapA]=BR_Array[swapB];
       BR_Array[swapB]=TempStore; 
    } 
    swapA+=NUM_FFT/2;                    //第二部分的交换
    swapB++; 
    if (swapB>swapA)
    {
       TempStore=BR_Array[swapA];
       BR_Array[swapA]=BR_Array[swapB];
       BR_Array[swapB]=TempStore;
    }
  }
}
/*=================================================================================================
04.名称:IntFFT
   入口:ReArray[]:
        ImArray[]:
   出口:无
   功能:FFT函数,对输入数组ReArray[]执行时间抽取的基2的FFT算法。在FFT算法的每一步,都要执行蝶形
        方程:

        	 Re1=Re1+(Cos(x)*Re2+Sin(x)*Im2)
             Re2=Re1-(Cos(x)*Re2+Sin(x)*Im2)
             Im1=Im1+(Cos(x)*Im2-Sin(x)*Re2)
             Im2=Im1-(Cos(x)*Im2-Sin(x)*Re2)

		程序使用如下值计算上式:

		     Re1=ReArray[indexA],Re2=ReArray[indexB]
             Im1=ImArray[indexA],Im2=ImArray[indexB]

		x =角度: 2*pi*(sin_index/NUM_FFT)单位:弧度;存储在代码空间SinTable[]数组中

		关键点:
		     1.	实部的数据在ReArray[]数组中,2的幂,以16-bit二进制格式存放,虚部假设全为0
			    存放在ImArray[]数组中。
			 2.	实部假设被以位反向格式存储。
			 3. 正弦和余弦值被事先计算好存放在表中,事实上,表中只保存了1/4周期的正弦值。
			 4. 为了优化代码,只用整形数计算(没有浮点操作),这样可以节省存储空间。FFT所
			    有的中间计算结果都以16-bit形式存储,故程序的精度有限。当输入数据少于16-bit
				时,数据左对齐在执行FFT可产生最好的计算结果。
			 5. FFT的算法为基-2算法,所以,采样点的个数必须为2^N,N为整数。最少的采样点个数
			    为4,常数NUM_FFT定义了采样点的个数。
			 6. 对输入数据进行优化,只有实部输入,虚部全部设置为0。在这一步中,删除了不必要
			    的重复部分,对于角度0这一点的计算,所有的sin值都时0,所有的cos值都是1。另外
				由于虚部为0,故计算时的值也都为等于0。
=================================================================================================*/
void IntFFT(int ReArray[],int ImArray[])
{
#if(NUM_FFT>=512)
  unsigned int sin_index,g_cnt,s_cnt;          // Keeps track of the proper index
  unsigned int indexA,indexB;                  // locations for each calculation
#endif

#if(NUM_FFT<=256)
  unsigned char sin_index,g_cnt,s_cnt;         // Keeps track of the proper index
  unsigned char indexA,indexB;                 // locations for each calculation
#endif

  unsigned int group=NUM_FFT/4,stage=2;
  long CosVal,SinVal;
  long TempImA,TempImB,TempReA,TempReB,TempReA2,TempReB2;
  IBALONG ReTwid,ImTwid,TempL;

  indexA=0;
  for(g_cnt=0;g_cnt<NUM_FFT/2;g_cnt++)
  {
    indexB=indexA+1;
    TempReA=ReArray[indexA];
    TempReB=ReArray[indexB];
  
    TempL.l=(long)TempReA+TempReB;	           //计算新的ReArray[indexA]的值
    if((TempL.l<0)&&(0x01&TempL.b[3])) TempReA2=(TempL.l>>1)+1;
    else TempReA2=TempL.l>>1;
     
    TempL.l=(long)TempReA-TempReB;	           //计算新的ReArray[indexB]的值
    if((TempL.l<0)&&(0x01&TempL.b[3])) ReArray[indexB]=(TempL.l>>1)+1;
    else ReArray[indexB]=TempL.l>>1;

    ReArray[indexA]=TempReA2;
    ImArray[indexA]=0;                         //将虚部设置为0
    ImArray[indexB]=0;
    indexA=indexB+1;
  }
  while(stage<=NUM_FFT/2)
  {
    indexA=0;
    sin_index=0;
    for(g_cnt=0;g_cnt<group;g_cnt++)
    {
      for(s_cnt=0;s_cnt<stage;s_cnt++)
      {
        indexB=indexA+stage;

        TempReA=ReArray[indexA];
        TempReB=ReArray[indexB];
        TempImA=ImArray[indexA];
        TempImB=ImArray[indexB];

        if(sin_index==0)                //"x"=0弧度
        {
          TempL.l=(long)TempReA+TempReB;//计算新的ReArray[indexA]的值
          if((TempL.l<0)&&(0x01&TempL.b[3])) TempReA2=(TempL.l>>1)+1;
          else TempReA2=TempL.l>>1;

          TempL.l=(long)TempReA-TempReB;//计算新的ReArray[indexB]的值
          if((TempL.l<0)&&(0x01&TempL.b[3])) TempReB2=(TempL.l>>1)+1;
          else TempReB2=TempL.l>>1;

          TempL.l=(long)TempImA-TempImB;//计算新的ImArray[indexB]的值
          if((TempL.l<0)&&(0x01&TempL.b[3])) TempImB=(TempL.l>>1)+1;
          else TempImB=TempL.l>>1;

          TempL.l=(long)TempImA+TempImB;//计算新的ImArray[indexA]的值
          if((TempL.l<0)&&(0x01&TempL.b[3])) TempImA=(TempL.l>>1)+1;
          else TempImA=TempL.l>>1;
        }
        else if(sin_index==NUM_FFT/4)   //"x"=pi/2弧度
        {
          TempL.l=(long)TempReA-TempImB;//计算新的ReArray[indexB]的值
          if((TempL.l<0)&&(0x01&TempL.b[3])) TempReB2=(TempL.l>>1)+1;
          else TempReB2=TempL.l>>1;

          TempL.l=(long)TempReA+TempImB;//计算新的ReArray[indexA]的值
          if((TempL.l<0)&&(0x01&TempL.b[3])) TempReA2=(TempL.l>>1)+1;
          else TempReA2=TempL.l>>1;

          TempL.l=(long)TempImA+TempReB;//计算新的ImArray[indexB]的值
          if((TempL.l<0)&&(0x01&TempL.b[3])) TempImB=(TempL.l>>1)+1;
          else TempImB=TempL.l>>1;

          TempL.l=(long)TempImA-TempReB;//计算新的ImArray[indexA]的值
          if((TempL.l<0)&&(0x01&TempL.b[3])) TempImA=(TempL.l>>1)+1;
          else TempImA=TempL.l>>1;
        }
        else
        {
          if(sin_index>NUM_FFT/4)		//如果没有上述情况,蝶形运算中的sin和cos值将通过查表得到。
          {
            SinVal=SinTable[(NUM_FFT/2)-sin_index];
            CosVal=-SinTable[sin_index -(NUM_FFT/4)];
          }
          else
          {
            SinVal=SinTable[sin_index];
            CosVal=SinTable[(NUM_FFT/4)-sin_index];
          }								//蝶形运算方程通过sin值和cos值来计算
          ReTwid.l=((long)TempReB*CosVal)+((long)TempImB*SinVal);	
          ImTwid.l=((long)TempImB*CosVal)-((long)TempReB*SinVal);
          
          TempL.i[1]=0;					//计算新的ReArray[indexA]的值
          TempL.i[0]=TempReA;			
          TempL.l=TempL.l>>1;
          ReTwid.l+=TempL.l;
          if((ReTwid.l<0)&&(ReTwid.i[1])) TempReA2=ReTwid.i[0]+1;
          else TempReA2=ReTwid.i[0];

          TempL.l=TempL.l<<1;		    //计算新的ReArray[indexB]的值
          TempL.l-=ReTwid.l;
          if((TempL.l<0)&&(TempL.i[1]))   TempReB2=TempL.i[0]+1;
          else TempReB2=TempL.i[0];

          TempL.i[1]=0;					//计算新的ImArray[indexA]的值
          TempL.i[0]=TempImA;
          TempL.l=TempL.l>>1;
          ImTwid.l+=TempL.l;
          if((ImTwid.l<0)&&(ImTwid.i[1])) TempImA=ImTwid.i[0]+1;
          else TempImA=ImTwid.i[0];

          TempL.l= TempL.l<<1;			//计算新的ImArray[indexB]的值
          TempL.l-=ImTwid.l;
          if((TempL.l<0)&&(TempL.i[1]))   TempImB=TempL.i[0]+1;
          else TempImB=TempL.i[0];
        }
        ReArray[indexA]=TempReA2;
        ReArray[indexB]=TempReB2;
        ImArray[indexA]=TempImA;
        ImArray[indexB]=TempImB;
        indexA++;
        sin_index+=group;
      }
      indexA=indexB+1;
      sin_index=0;
    }
    group/=2;
    stage*=2;
  }
}
/*=================================================================================================
12.名称:ADC0_ISR
   入口:无
   出口:无
   功能:ADC0中断服务子程序
=================================================================================================*/
void ADC0_ISR(void) interrupt 15 using 3
{
  ADCINT=0;                       //清ADC转换标志位
  Real[ADC_Index]=ADC0;           //存ADC的转换值
  ADC_Index++;                    //采样次数加1
  if (ADC_Index>=NUM_FFT)         //达到采样数
  {
    Conversion_Set_Complete=1;    //标志主程序
    EIE2&=~0x02;                  //ADC中断禁能
  }
}
/*-----------------------------------------------------------------------------------------------*/
//FFT_New_Test.c

⌨️ 快捷键说明

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