久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 32158|回復: 45
打印 上一主題 下一主題
收起左側

FFT算法的使用說明與C語言版實現源碼

  [復制鏈接]
跳轉到指定樓層
樓主
如果對時間要求不是很高的話,用51單片機做fft計算進行頻率分析也可以熟悉算法并了解fft的本質


FFT使用說明
性能:
64點  :1.50299ms
128點 :3.09864ms
使用方法指導:
1,需要兩個文件,fft_fp.c和fft_fp.h
2,根據需求修改fft_fp.h中的采樣點數FFT_N,采樣點數以宏定義的方式定義
3,外部聲明兩個全局變量,已經在fft_fp.c中定義
    extern struct compx s[FFT_N];     //FFT輸入和輸出:從S[0]開始存放,根據大小自己定義
    extern float SIN_TAB[FFT_N/4+1];  //正弦信號表
4,調用create_sin_tab(float *sin_t)函數將正弦信號數據表生成在內存中,比如這樣調用create_sin_tab(SIN_TAB);
5,采樣數據,將ADC采樣的數據按自然序列放在s的實部,虛部為0
6,調用FFT(struct compx *xin)函數開始計算,計算結果也存放在xin中,比如我們這樣調用:FFT(s),結果存放在s中
7,計算每個頻點的模值,計算方法如下:
    for(i=1;i<FFT_N/2;i++){          //求變換后結果的模值,存入復數的實部部分
        s[ i].real=sqrt(s[ i].real*s[ i].real+s[ i].imag*s[ i].imag)/(i=0?FFT_N:(FFT_N/2));
    }
8,大功告成!



單片機源程序如下:
  1. /*********************************************************************
  2.                          快速福利葉變換C程序包
  3. 函數簡介:此程序包是通用的快速傅里葉變換C語言函數,移植性強,以下部分不依
  4.           賴硬件。此程序包采用聯合體的形式表示一個復數,輸入為自然順序的復
  5.           數(輸入實數是可令復數虛部為0),輸出為經過FFT變換的自然順序的
  6.           復數.此程序包可在初始化時調用create_sin_tab()函數創建正弦函數表,
  7.           以后的可采用查表法計算耗時較多的sin和cos運算,加快可計算速度.與
  8.           Ver1.1版相比較,Ver1.2版在創建正弦表時只建立了1/4個正弦波的采樣值,
  9.           相比之下節省了FFT_N/4個存儲空間
  10. 使用說明:使用此函數只需更改宏定義FFT_N的值即可實現點數的改變,FFT_N的
  11.           應該為2的N次方,不滿足此條件時應在后面補0。若使用查表法計算sin值和
  12.           cos值,應在調用FFT函數前調用create_sin_tab()函數創建正弦表
  13. 函數調用:FFT(s);
  14. 作    者:吉帥虎
  15. 時    間:2010-2-20
  16. 版    本:Ver1.2
  17. 參考文獻:  
  18. **********************************************************************/
  19. #include <math.h>
  20. #include "fft_fp.h"

  21. //#define FFT_N 64                                                   //定義福利葉變換的點數
  22. //#define PI 3.1415926535897932384626433832795028841971               //定義圓周率值
  23. //
  24. //struct compx {float real,imag;};                                    //定義一個復數結構
  25. struct compx s[FFT_N];                                              //FFT輸入和輸出:從S[0]開始存放,根據大小自己定義
  26. float SIN_TAB[FFT_N/4+1];                                             //定義正弦表的存放空間

  27. /*******************************************************************
  28. 函數原型:struct compx EE(struct compx b1,struct compx b2)  
  29. 函數功能:對兩個復數進行乘法運算
  30. 輸入參數:兩個以聯合體定義的復數a,b
  31. 輸出參數:a和b的乘積,以聯合體的形式輸出
  32. *******************************************************************/
  33. struct compx EE(struct compx a,struct compx b)      
  34. {
  35. struct compx c;
  36. c.real=a.real*b.real-a.imag*b.imag;
  37. c.imag=a.real*b.imag+a.imag*b.real;
  38. return(c);
  39. }

  40. /******************************************************************
  41. 函數原型:void create_sin_tab(float *sin_t)
  42. 函數功能:創建一個正弦采樣表,采樣點數與福利葉變換點數相同
  43. 輸入參數:*sin_t存放正弦表的數組指針
  44. 輸出參數:無
  45. ******************************************************************/
  46. void create_sin_tab(float *sin_t)                     
  47. {
  48.   int i;
  49.   for(i=0;i<=FFT_N/4;i++)
  50.   sin_t[ i]=sin(2*PI*i/FFT_N);
  51. }
  52. /******************************************************************
  53. 函數原型:void sin_tab(float pi)
  54. 函數功能:采用查表的方法計算一個數的正弦值
  55. 輸入參數:pi 所要計算正弦值弧度值,范圍0--2*PI,不滿足時需要轉換
  56. 輸出參數:輸入值pi的正弦值
  57. ******************************************************************/
  58. float sin_tab(float pi)
  59. {
  60.   int n;
  61.   float a=0;
  62.    n=(int)(pi*FFT_N/2/PI);
  63.    
  64.   if(n>=0&&n<=FFT_N/4)
  65.     a=SIN_TAB[n];
  66.   else if(n>FFT_N/4&&n<FFT_N/2)
  67.     {
  68.      n-=FFT_N/4;
  69.      a=SIN_TAB[FFT_N/4-n];
  70.     }
  71.   else if(n>=FFT_N/2&&n<3*FFT_N/4)
  72.     {
  73.      n-=FFT_N/2;
  74.      a=-SIN_TAB[n];
  75.    }
  76.   else if(n>=3*FFT_N/4&&n<3*FFT_N)
  77.     {
  78.      n=FFT_N-n;
  79.      a=-SIN_TAB[n];
  80.    }
  81.   
  82.   return a;
  83. }
  84. /******************************************************************
  85. 函數原型:void cos_tab(float pi)
  86. 函數功能:采用查表的方法計算一個數的余弦值
  87. 輸入參數:pi 所要計算余弦值弧度值,范圍0--2*PI,不滿足時需要轉換
  88. 輸出參數:輸入值pi的余弦值
  89. ******************************************************************/
  90. float cos_tab(float pi)
  91. {
  92.    float a,pi2;
  93.    pi2=pi+PI/2;
  94.    if(pi2>2*PI)
  95.      pi2-=2*PI;
  96.    a=sin_tab(pi2);
  97.    return a;
  98. }
  99. /*****************************************************************
  100. 函數原型:void FFT(struct compx *xin,int N)
  101. 函數功能:對輸入的復數組進行快速傅里葉變換(FFT)
  102. 輸入參數:*xin復數結構體組的首地址指針,struct型
  103. 輸出參數:無
  104. *****************************************************************/
  105. void FFT(struct compx *xin)
  106. {
  107.   register int f,m,nv2,nm1,i,k,l,j=0;
  108.   struct compx u,w,t;
  109.    
  110.    nv2=FFT_N/2;                  //變址運算,即把自然順序變成倒位序,采用雷德算法
  111.    nm1=FFT_N-1;  
  112.    for(i=0;i<nm1;i++)        
  113.    {
  114.     if(i<j)                    //如果i<j,即進行變址
  115.      {
  116.       t=xin[j];           
  117.       xin[j]=xin[ i];
  118.       xin[ i]=t;
  119.      }
  120.     k=nv2;                    //求j的下一個倒位序
  121.     while(k<=j)               //如果k<=j,表示j的最高位為1   
  122.      {           
  123.       j=j-k;                 //把最高位變成0
  124.       k=k/2;                 //k/2,比較次高位,依次類推,逐個比較,直到某個位為0
  125.      }
  126.    j=j+k;                   //把0改為1
  127.   }
  128.                         
  129.   {
  130.    int le,lei,ip;                            //FFT運算核,使用蝶形運算完成FFT運算
  131.     f=FFT_N;
  132.    for(l=1;(f=f/2)!=1;l++)                  //計算l的值,即計算蝶形級數
  133.            ;
  134.   for(m=1;m<=l;m++)                         // 控制蝶形結級數
  135.    {                                        //m表示第m級蝶形,l為蝶形級總數l=log(2)N
  136.     le=2<<(m-1);                            //le蝶形結距離,即第m級蝶形的蝶形結相距le點
  137.     lei=le/2;                               //同一蝶形結中參加運算的兩點的距離
  138.     u.real=1.0;                             //u為蝶形結運算系數,初始值為1
  139.     u.imag=0.0;
  140.     //w.real=cos(PI/lei);                  //不適用查表法計算sin值和cos值
  141.     // w.imag=-sin(PI/lei);
  142.     w.real=cos_tab(PI/lei);                //w為系數商,即當前系數與前一個系數的商
  143.     w.imag=-sin_tab(PI/lei);
  144.     for(j=0;j<=lei-1;j++)                  //控制計算不同種蝶形結,即計算系數不同的蝶形結
  145.      {
  146.       for(i=j;i<=FFT_N-1;i=i+le)           //控制同一蝶形結運算,即計算系數相同蝶形結
  147.        {
  148.         ip=i+lei;                          //i,ip分別表示參加蝶形運算的兩個節點
  149.         t=EE(xin[ip],u);                   //蝶形運算,詳見公式
  150.         xin[ip].real=xin[ i].real-t.real;
  151.         xin[ip].imag=xin[ i].imag-t.imag;
  152.         xin[ i].real=xin[ i].real+t.real;
  153.         xin[ i].imag=xin[ i].imag+t.imag;
  154.        }
  155.       u=EE(u,w);                          //改變系數,進行下一個蝶形運算
  156.      }
  157.    }
  158.   }
  159.   
  160. }

  161. /************************************************************
  162. 函數原型:void main()
  163. 函數功能:測試FFT變換,演示函數使用方法
  164. 輸入參數:無
  165. 輸出參數:無
  166. ************************************************************/

復制代碼

所有資料51hei提供下載:
FFT的C語言版.rar (3.45 KB, 下載次數: 955)


評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏29 分享淘帖 頂4 踩
回復

使用道具 舉報

來自 2#
ID:477236 發表于 2019-9-16 15:23 | 只看該作者
/*****************************************************************
函數原型:void IFFT(struct compx *xin)
函數功能:對輸入的復數組進行快速逆傅里葉變換(IFFT)
輸入參數:*xin復數結構體組的首地址指針,struct型
輸出參數:無
作者:瓶子
*****************************************************************/
void IFFT(struct compx *xin)
{
        float temp;
        int i;

        xin[0].real /= FFT_N;                                xin[0].imag /= FFT_N;
        xin[FFT_N >> 1].real /= FFT_N;        xin[FFT_N >> 1].imag /= FFT_N;

        for (i = 1; i < FFT_N >> 1; i++)
        {
                temp = xin[i].real / FFT_N;
                xin[i].real = xin[FFT_N - i].real / FFT_N;
                xin[FFT_N - i].real = temp;
                temp = xin[i].imag / FFT_N;
                xin[i].imag = xin[FFT_N - i].imag / FFT_N;
                xin[FFT_N - i].imag = temp;
        }
        FFT(xin);
}

基于以上代碼的逆FFT參考代碼,希望大家有用

評分

參與人數 1黑幣 +20 收起 理由
admin + 20 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

板凳
ID:340401 發表于 2018-7-20 10:20 | 只看該作者
請問還需要用到什么程序嗎,能不能給個完整的ad采樣然后FFT的呢
回復

使用道具 舉報

地板
ID:340401 發表于 2018-7-20 10:24 | 只看該作者
這里是沒有ad采樣函數嗎,能不能給個完整的有ad采樣的FFT的程序呢
回復

使用道具 舉報

5#
ID:254919 發表于 2018-7-20 17:41 | 只看該作者
同求,謝謝樓主
回復

使用道具 舉報

6#
ID:377035 發表于 2018-7-22 05:48 | 只看該作者
51單片機作FFT會不會出現存儲空間不足的問題啊?有AD采樣的程序嗎?
回復

使用道具 舉報

7#
ID:385237 發表于 2018-8-12 10:20 | 只看該作者
有誰試用過可行嗎?
回復

使用道具 舉報

8#
ID:385237 發表于 2018-8-12 11:18 | 只看該作者
我試了一下,keil編譯的時候顯示空間不足,郁悶了。
回復

使用道具 舉報

9#
ID:263813 發表于 2018-10-3 22:52 | 只看該作者
可以使用,結果還在測試中,調用create_sin_tab得改改
回復

使用道具 舉報

10#
ID:124617 發表于 2018-10-27 10:38 | 只看該作者
不錯,正在搞信號處理方面的
回復

使用道具 舉報

11#
ID:235223 發表于 2018-12-6 17:13 | 只看該作者
有誰試用過可行嗎
回復

使用道具 舉報

12#
ID:453542 發表于 2018-12-24 15:31 | 只看該作者
下下來測試下先。
回復

使用道具 舉報

13#
ID:460795 發表于 2019-1-3 11:28 | 只看該作者
下來看看
回復

使用道具 舉報

14#
ID:460863 發表于 2019-1-3 13:02 | 只看該作者
請問還需要用到什么程序嗎,能不能給個完整的ad采樣然后FFT的呢
回復

使用道具 舉報

15#
ID:95916 發表于 2019-1-9 10:14 | 只看該作者
感謝分享,研究一下
回復

使用道具 舉報

16#
ID:490893 發表于 2019-3-16 15:16 | 只看該作者
我怎么測試下來 時間遠遠不止呢,我用的24MHZ 的 STC51     執行128 的 FFT 需要 50多mS啊
回復

使用道具 舉報

17#
ID:500722 發表于 2019-4-12 15:38 | 只看該作者
打算移植試一試
回復

使用道具 舉報

18#
ID:500722 發表于 2019-4-12 18:01 | 只看該作者
樓主你好,測試算出來的誤差有點大是什么原因

fx = 1500 * sin(PI * 2 * i * 350.0 / 44800) +
             2700 * sin(PI * 2 * i * 8400.0 / 44800) +
             4000 * sin(PI * 2* i * 18550.0 / 44800);

i: 1, 350  - 1515.876709
i: 2, 700  - 0.000037
i: 3, 1050  - 13.832612
i: 4, 1400  - 0.000021
i: 5, 1750  - 0.000106
i: 6, 2100  - 0.000004
i: 7, 2450  - 63.505074
i: 8, 2800  - 28.065117
i: 9, 3150  - 8.681163
i: 10, 3500  - 0.000003
i: 11, 3850  - 27.872404
i: 12, 4200  - 0.000009
i: 13, 4550  - 28.500025
i: 14, 4900  - 0.000009
i: 15, 5250  - 0.000394
i: 16, 5600  - 0.000023
i: 17, 5950  - 0.000057
i: 18, 6300  - 0.000031
i: 19, 6650  - 14.382548
i: 20, 7000  - 0.000009
i: 21, 7350  - 117.270576
i: 22, 7700  - 0.000043
i: 23, 8050  - 23.529263
i: 24, 8400  - 2862.641113
i: 25, 8750  - 3.221907
i: 26, 9100  - 0.000009
i: 27, 9450  - 0.000341
i: 28, 9800  - 0.000022
i: 29, 10150  - 43.866310
i: 30, 10500  - 0.000080
i: 31, 10850  - 67.757050
i: 32, 11200  - 0.000032
i: 33, 11550  - 1.971847
i: 34, 11900  - 0.000046
i: 35, 12250  - 16.637976
i: 36, 12600  - 0.000021
i: 37, 12950  - 0.000365
i: 38, 13300  - 0.000002
i: 39, 13650  - 15.182350
i: 40, 14000  - 67.564186
i: 41, 14350  - 2.074305
i: 42, 14700  - 0.000011
i: 43, 15050  - 60.110844
i: 44, 15400  - 0.000009
i: 45, 15750  - 122.913864
i: 46, 16100  - 0.000014
i: 47, 16450  - 0.000136
i: 48, 16800  - 0.000023
i: 49, 17150  - 0.000022
i: 50, 17500  - 0.000009
i: 51, 17850  - 25.744360
i: 52, 18200  - 0.000009
i: 53, 18550  - 4473.796387
i: 54, 18900  - 0.000032
i: 55, 19250  - 13.660447
i: 56, 19600  - 89.433647
i: 57, 19950  - 1.869473
i: 58, 20300  - 0.000012
i: 59, 20650  - 0.000831
i: 60, 21000  - 0.000022
i: 61, 21350  - 128.387222
i: 62, 21700  - 0.000014
i: 63, 22050  - 66.304977
回復

使用道具 舉報

19#
ID:457471 發表于 2019-4-13 12:04 | 只看該作者
感謝分享!
回復

使用道具 舉報

20#
ID:474344 發表于 2019-4-22 22:02 | 只看該作者
挺好學習學習
回復

使用道具 舉報

21#
ID:374767 發表于 2019-4-27 15:29 | 只看該作者
感謝分享
回復

使用道具 舉報

22#
ID:500396 發表于 2019-5-16 08:38 | 只看該作者
謝謝樓主分享!
回復

使用道具 舉報

23#
ID:578513 發表于 2019-7-5 15:15 | 只看該作者
謝謝樓主分享!
回復

使用道具 舉報

24#
ID:583141 發表于 2019-7-27 09:30 | 只看該作者
感謝樓主
回復

使用道具 舉報

25#
ID:235062 發表于 2019-8-23 16:26 | 只看該作者
下載了,等有時間看看
回復

使用道具 舉報

26#
ID:553031 發表于 2019-9-29 05:04 來自手機 | 只看該作者
謝謝分享!
回復

使用道具 舉報

27#
ID:168554 發表于 2019-9-29 15:38 | 只看該作者
LeoXie 發表于 2019-4-12 18:01
樓主你好,測試算出來的誤差有點大是什么原因

fx = 1500 * sin(PI * 2 * i * 350.0 / 44800) +

我雖然不懂,但是我看你的三角生成的有問題呀。。/ 44800 這事采樣頻率吧,這個應該是/采樣點數呀。。
回復

使用道具 舉報

28#
ID:662720 發表于 2019-12-12 20:04 | 只看該作者
感謝分享,等有積分了馬上下載
回復

使用道具 舉報

29#
ID:67123 發表于 2020-2-26 09:47 | 只看該作者
這個也是查表嗎?
回復

使用道具 舉報

30#
ID:381834 發表于 2020-4-18 23:16 | 只看該作者
學習了,謝謝樓主分享!
回復

使用道具 舉報

31#
ID:514250 發表于 2020-6-1 13:33 | 只看該作者
感謝樓主分享
回復

使用道具 舉報

32#
ID:596103 發表于 2020-10-10 09:11 | 只看該作者
感謝分享,這個有采樣的程序嗎
回復

使用道具 舉報

33#
ID:828979 發表于 2020-10-12 22:39 | 只看該作者
這個程序沒怎么看懂
回復

使用道具 舉報

34#
ID:398872 發表于 2020-11-7 13:00 | 只看該作者

感謝樓主分享
回復

使用道具 舉報

35#
ID:615301 發表于 2021-1-28 02:57 | 只看該作者
感謝樓主分享
回復

使用道具 舉報

36#
ID:582255 發表于 2021-1-28 11:32 | 只看該作者
有采樣的函數嗎?先采樣再FFT這樣才更有實用價值啊
回復

使用道具 舉報

37#
ID:227340 發表于 2021-7-20 18:48 | 只看該作者
s[ i].real=sqrt(s[ i].real*s[ i].real+s[ i].imag*s[ i].imag)/(i=0?FFT_N:(FFT_N/2));
里面i=0?是什么意思 有bug吧
回復

使用道具 舉報

38#
ID:227340 發表于 2021-7-21 11:02 | 只看該作者
為什么計算出來的幅值都是零點幾
回復

使用道具 舉報

39#
ID:227340 發表于 2021-7-21 11:25 | 只看該作者
為什么要除以FFT_N/2
回復

使用道具 舉報

40#
ID:934203 發表于 2021-9-7 09:24 | 只看該作者
MCU丶NOOB 發表于 2021-7-20 18:48
s[ i].real=sqrt(s[ i].real*s[ i].real+s[ i].imag*s[ i].imag)/(i=0?FFT_N:(FFT_N/2));
里面i=0?是什么 ...

某頻率點的幅值為:該點復數的模值除以N/2(n=1時是直流分量,其幅值是該點的模值除以N)。
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 久久精品一区 | 国产91视频免费 | 日本天堂视频在线观看 | 亚洲欧美网 | 日韩欧美一级片 | 久久亚洲91| 91国产精品 | 天天爽夜夜爽精品视频婷婷 | 在线免费小视频 | 国产精品一二三区 | 欧美中文字幕一区二区三区亚洲 | 国产japanhdxxxx麻豆 | 精品欧美乱码久久久久久 | 日韩精品一区二区三区中文在线 | 欧美激情在线精品一区二区三区 | 天天影视网天天综合色在线播放 | 精品一区二区三区在线观看国产 | 蜜桃传媒一区二区 | 国产综合网址 | 国产黄色在线观看 | 日本成人在线免费视频 | 国产探花在线精品一区二区 | 国产婷婷综合 | 国产精品久久久亚洲 | 久久国产精品99久久久大便 | 日日草天天干 | 日韩视频免费看 | 日本午夜网 | 国产黄色av网站 | 欧美日韩精品在线免费观看 | 成人午夜精品 | 夜夜操天天艹 | 男人亚洲天堂 | 一级片在线观看 | 日韩欧美在线视频 | 成人在线观看黄 | 欧美一区二区三区四区视频 | 91日日| 欧洲精品一区 | 国产网站在线免费观看 | 色爱综合|