基于MSP432的FFT运算(计算频率、失真度等等)

开头

        在解决信号问题时,可根据FFT(快速傅立叶变换)快速根据单片机ADC获取到的数据进行处理,得到信号的频率和失真度等等信息。以下是我在参加电赛时,通过MSP432Y401单片机进行配置时的FFT配置。

FFT处理数据函数

        函数内部一些变量需要外部声明,也可自己根据函数进行更改,个人认为自己更改更有助于自己理解代码的含义。

        一些定义:

/* Define for Samples to be captured and Sampling Frequency */
#define NUM_SAMPLES 1024      //采样点数宏定义
#define SAMP_FREQ   64000     //采样频率定义


float Data_Real[NUM_SAMPLES];         //实部
float Data_Image[NUM_SAMPLES];        //虚部
void My_FFT()
{
   int i,j,k,m11,k1,ip,m,n,ff1=1;
   int l11,l21;
  //float l11,l21,t1,t2,pi,w1,w2,v1,v2,d,v11,v22;
   float tr,ti,pi,w1,w2,v1,v2,d,v11,v22;
   n=NUM_SAMPLES;j=0;m=(int)(log(NUM_SAMPLES)/log(2));
   for(i=0;i<=(n-1);i++)
   {
	 if(i>=j) goto L100;
	 tr=Data_Real[j];
         ti=Data_Image[j];
         Data_Real[j]=Data_Real[i];
	 Data_Image[j]=Data_Image[i];
         Data_Real[i]=tr;
         Data_Image[i]=ti;
	L100: k=n/2;
	L110: if(j<k||k==0) goto L120;
	    j=j-k;k=k/2;
        goto L110;
        L120: j=j+k;
    }
   
  for(m11=1;m11<=m;m11++)   //for(m11=1;m11<=m1;m11++)
   {
      l11=(int)pow(2,m11);
    // l11=1<<m11;
      l21=l11/2;
     //pi=3.14159265/l21;
      v1=1.0;
      v2=0.0;
       pi=4.0*atan(1.0)/l21;  //add计算圆周率的近似值
       w1=cos(pi);
       w2=-sin(pi);
	  for(k1=1;k1<=l21;k1++)//
	   {
	       d=ff1*v2;
		  for(i=(k1-1);i<=(n-1-l11+k1);i+=l11)
		   {
		      ip=i+l21;
		      tr=Data_Real[ip]*v1-Data_Image[ip]*d;//-
		      ti=Data_Image[ip]*v1+Data_Real[ip]*d;//+
		      Data_Real[ip]=Data_Real[i]-tr;//-
		      Data_Image[ip]=Data_Image[i]-ti;//-
		       Data_Real[i]= Data_Real[i]+tr;//+
		      Data_Image[i]=Data_Image[i]+ti;//+
		   }
            v11=v1*w1-v2*w2;
	     v22=v2*w1+v1*w2;
	     v1=v11;
	     v2=v22;
	     }
    }
 }

处理被FFT数据处理后的数据 

        ADC采样后的数据通过FFT处理后我们就可以拿来使用了,可以用这些数据进行计算,得到频率、失真度等等信息。

        处理函数(供参考,供修改):

/*----------数据处理----------------------------------*/
void Handle()
{
   int i; 
   int Freq_Scle_Value;
   float y,Total;
   float Vmax;
   float V_1KHz,V_2KHz,V_3KHz,V_4KHz,V_5KHz;
  /*---------------幅度谱------------------------------*/ 
    for(i=0;i<NUM_SAMPLES;i++)
   {
      y=sqrt(pow(Data_Real[i],2)+pow(Data_Image[i],2));
      Data_Real[i]=y;             
      //Data_Real[i]=y/2.0;
   }
	 for(i = 0;i < NUM_SAMPLES;i ++)
   {
	   Data_Real[i] = Data_Real[i] / 377;
   }	
   /*-----计算失真度------------------------------------*/
 //  if(S1_mark==1){
   if(state_num == 1 || state_num == 2){
     /*--------找幅度谱最大值,计算信号频率---------------------*/
      Vmax=Data_Real[1];
      for(i=1;i<NUM_SAMPLES/2;i++)
     {
       if(Vmax<=Data_Real[i]){
	    Vmax=Data_Real[i];
            Freq_Scle_Value=i;
       } //end if
      }//end for
    /*--------计算THD------------------------------------*/
   //   V_1KHz=Data_Real[2];//4,2
     // V_2KHz=Data_Real[4];//8,4
     // V_3KHz=Data_Real[6];//12,6
     // V_4KHz=Data_Real[8];//16,8
    //  V_5KHz=Data_Real[10];//20,10
       V_1KHz=Data_Real[Freq_Scle_Value*1];//4,2
       V_2KHz=Data_Real[Freq_Scle_Value*2];//8,4
       V_3KHz=Data_Real[Freq_Scle_Value*3];//12,6
       V_4KHz=Data_Real[Freq_Scle_Value*4];//16,8
       V_5KHz=Data_Real[Freq_Scle_Value*5];//20,10
      Total=pow(V_2KHz,2)+pow(V_3KHz,2)+pow(V_4KHz,2)+pow(V_5KHz,2);
      THD=sqrt(Total)/V_1KHz;
       Vo_First=V_1KHz;
   }
   /*-----虚部清零-----------------------------*/ 
   for(i=0;i<NUM_SAMPLES;i++)
     Data_Image[i]=0.0;
   /*--------通过找幅度谱最大值,计算信号频率-----------------------------*/
    if(state_num == 2 | state_num == 3){
     Vmax=Data_Real[1];
     for(i=1;i<NUM_SAMPLES/2;i++)
     {
       if(Vmax<=Data_Real[i]){
	    Vmax=Data_Real[i];        
            Freq_Scle_Value=i;
       } //end if
      }//end for           公式:fk = fs/N *k
		  //Freq=(float)Freq_Scle_Value * 1.00f;//采样率128K
			//Freq=(float)Freq_Scle_Value * 0.03125f;//采样率64K 2048
			Freq=(float)Freq_Scle_Value * 0.0625f;
      //Freq=(float)Freq_Scle_Value * 0.500f;//采样率64K 128
    // Freq=(float)Freq_Scle_Value*0.2500;//32KHz
    }
}

总结

        FFT对于做信号题还是很有用处的,但是理解起来还是非常困难的,也有着更好的FFT数据处理代码,本文章的FFT数据处理代码仅供参考和学习。(代码本人都成功运行,并且运用到了2023年的电赛上。并且获得了奖项)希望大家可以慢慢学习,提升自己的水平。

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值