[MM32软件] fft算法

[复制链接]
908|1
 楼主| chenci2013 发表于 2023-11-19 20:00 | 显示全部楼层 |阅读模式


  1. #include <math.h>
  2. #include "OLED.h"
  3. #define FFT_N 64                                                   //定义福利叶变换的点数
  4. #define PI 3.1415926535897932384626433832795028841971               //定义圆周率值
  5. #define Process_sensitivity        0                                                                                //修改Process_sensitivity的数值个调整频谱变化幅度,不建议超过4
  6. unsigned char tmrcnt=0;
  7. float ADC_OutBuf[FFT_N/4];
  8. struct compx ADC_InBuf[FFT_N];                                      //FFT输入和输出:从S[0]开始存放,根据大小自己定义
  9. float SIN_TAB[FFT_N/4+1];                                           //定义正弦表的存放空间
  10. struct compx {float real,imag;};

  11. struct compx EE(struct compx a,struct compx b)      
  12. {
  13. struct compx c;
  14. c.real=a.real*b.real-a.imag*b.imag;
  15. c.imag=a.real*b.imag+a.imag*b.real;
  16. return(c);
  17. }

  18. void create_sin_tab(float *sin_t)                     
  19. {
  20.   int i;
  21.   for(i=0;i<=FFT_N/4;i++)
  22.   sin_t[i]=sin(2*PI*i/FFT_N);
  23. }

  24. float sin_tab(float pi)
  25. {
  26.   int n;
  27.   float a=0;
  28.    n=(int)(pi*FFT_N/2/PI);
  29.    
  30.   if(n>=0&&n<=FFT_N/4)
  31.     a=SIN_TAB[n];
  32.   else if(n>FFT_N/4&&n<FFT_N/2)
  33.     {
  34.      n-=FFT_N/4;
  35.      a=SIN_TAB[FFT_N/4-n];
  36.     }
  37.   else if(n>=FFT_N/2&&n<3*FFT_N/4)
  38.     {
  39.      n-=FFT_N/2;
  40.      a=-SIN_TAB[n];
  41.    }
  42.   else if(n>=3*FFT_N/4&&n<3*FFT_N)
  43.     {
  44.      n=FFT_N-n;
  45.      a=-SIN_TAB[n];
  46.    }
  47.   
  48.   return a;
  49. }

  50. float cos_tab(float pi)
  51. {
  52.    float a,pi2;
  53.    pi2=pi+PI/2;
  54.    if(pi2>2*PI)
  55.      pi2-=2*PI;
  56.    a=sin_tab(pi2);
  57.    return a;
  58. }

  59. void FFT(struct compx *xin)
  60. {
  61.   register int f,m,nv2,nm1,i,k,l,j=0;
  62.   struct compx u,w,t;
  63.    
  64.    nv2=FFT_N/2;                  //变址运算,即把自然顺序变成倒位序,采用雷德算法
  65.    nm1=FFT_N-1;  
  66.    for(i=0;i<nm1;i++)        
  67.    {
  68.     if(i<j)                    //如果i<j,即进行变址
  69.      {
  70.       t=xin[j];           
  71.       xin[j]=xin[i];
  72.       xin[i]=t;
  73.      }
  74.     k=nv2;                    //求j的下一个倒位序
  75.     while(k<=j)               //如果k<=j,表示j的最高位为1   
  76.      {           
  77.       j=j-k;                 //把最高位变成0
  78.       k=k/2;                 //k/2,比较次高位,依次类推,逐个比较,直到某个位为0
  79.      }
  80.    j=j+k;                   //把0改为1
  81.   }
  82.                         
  83.   {
  84.    int le,lei,ip;                            //FFT运算核,使用蝶形运算完成FFT运算
  85.     f=FFT_N;
  86.    for(l=1;(f=f/2)!=1;l++)                  //计算l的值,即计算蝶形级数
  87.            ;
  88.   for(m=1;m<=l;m++)                         // 控制蝶形结级数
  89.    {                                        //m表示第m级蝶形,l为蝶形级总数l=log(2)N
  90.     le=2<<(m-1);                            //le蝶形结距离,即第m级蝶形的蝶形结相距le点
  91.     lei=le/2;                               //同一蝶形结中参加运算的两点的距离
  92.     u.real=1.0;                             //u为蝶形结运算系数,初始值为1
  93.     u.imag=0.0;
  94.     w.real=cos_tab(PI/lei);                //w为系数商,即当前系数与前一个系数的商
  95.     w.imag=-sin_tab(PI/lei);
  96.     for(j=0;j<=lei-1;j++)                  //控制计算不同种蝶形结,即计算系数不同的蝶形结
  97.      {
  98.       for(i=j;i<=FFT_N-1;i=i+le)           //控制同一蝶形结运算,即计算系数相同蝶形结
  99.        {
  100.         ip=i+lei;                          //i,ip分别表示参加蝶形运算的两个节点
  101.         t=EE(xin[ip],u);                   //蝶形运算,详见公式
  102.         xin[ip].real=xin[i].real-t.real;
  103.         xin[ip].imag=xin[i].imag-t.imag;
  104.         xin[i].real=xin[i].real+t.real;
  105.         xin[i].imag=xin[i].imag+t.imag;
  106.        }
  107.       u=EE(u,w);                          //改变系数,进行下一个蝶形运算
  108.      }
  109.    }
  110.   }
  111.   
  112. }


daichaodai 发表于 2023-11-20 08:29 来自手机 | 显示全部楼层
采集交流电压和电流的时候就会用到FFT算法
您需要登录后才可以回帖 登录 | 注册

本版积分规则

125

主题

6670

帖子

4

粉丝
快速回复 在线客服 返回列表 返回顶部