分享自己编写简单易懂的FFT程序

2019-12-31 19:12发布

本帖最后由 10xjzheng 于 2016-6-1 21:45 编辑

单片机只是工具,没有思想怎么行?最近看了些信号处理方面的书籍,开始自己实现一些算法。本FFT程序是自己看书看懂后完全自己写出来的,
因为看不懂别人写的,效率上大致跟一般的程序没有区别,但是由于没有用在实际中用到,所以小细节方面的效率可能还需要优化,但是在我感
觉我写的思路比较清晰。画说回来,实现完后本来可以搞个频谱FFT玩玩,但是不知道为什么一点兴趣都没有了。

下面两本是很好的书籍,第二本讲道理讲到我都想推公式了,还是公式简单明了,也侧面反应了书籍很不错,然后去看到安富莱的FFT教程,大部
分也是抄这本书里面的内容,虽然有说是抄的,但是也......我的程序是参考第一本书中讲解的内容编写的,主要看P183页的图。
PS:书本可以上网上二手书店买,很便宜,大学的很专业的书籍又没有多少人学会的最便宜了 包括邮费通常特厚的20块钱就买到了。

参考书籍:
《深入浅出数字信号处理》
《实用数字信号处理 从原理到应用》



参考网页:
基础的概念
http://www.360doc.com/content/13/0328/12/202378_274443797.shtml

清晰的推导过程
http://blog.sina.com.cn/s/blog_57ad1bd20100txgs.html

FFT结果的物理意义
http://blog.sina.com.cn/s/blog_640029b301010xkv.html


MyFFT.zip (2.76 MB, 下载次数: 130) 2016-6-1 21:22 上传 点击文件名下载附件
  1. //FFT处理
  2. //本算法为了清晰明了,就没有省略一些中间变量
  3. void MyFFT(struct ComplexNbr *OriginalBuff,unsigned int BuffLength)
  4. {
  5.         unsigned char OrderCnt;
  6.         unsigned int NbrOfBigDieXing,CntOfBigDieXing,i,NbrOfDataInPerBigDieXing,NbrOfLittleDieXingInBigDiexing,CntOfLittleDieXing;
  7.         struct ComplexNbr TempComplexNbr;
  8.         unsigned int Index0,Index1;

  9.         //最外层循环,FFT级数
  10.         for (OrderCnt = 1; OrderCnt <=FFT_ORDER;OrderCnt++)
  11.         {
  12.                 NbrOfBigDieXing = 1;

  13. #if DEBUG==1
  14.                 printf("当前蝶形运算的级数是%d ",OrderCnt);
  15. #endif

  16.                 //首先计算出蝶形运算的个数,一开始是2^(FFT_ORDER - OrderCnt)
  17.                 for (i=0;i<(FFT_ORDER - OrderCnt);i++)
  18.                 {
  19.                         NbrOfBigDieXing *= 2;
  20.                 }

  21. #if DEBUG==1
  22.                 printf("大蝶形运算的个数是:%d ",NbrOfBigDieXing);
  23. #endif

  24.                 //每个蝶形运算中的个数
  25.                 NbrOfDataInPerBigDieXing = TOTAL_NBR/NbrOfBigDieXing;
  26.                 NbrOfLittleDieXingInBigDiexing = NbrOfDataInPerBigDieXing/2;

  27. #if DEBUG==1
  28.                 printf("每个大蝶形运算的数字有%d个,每个大的蝶形运算有%d个小的蝶形运算 ",NbrOfDataInPerBigDieXing,NbrOfLittleDieXingInBigDiexing);
  29. #endif
  30.                
  31.                 //第二层循环——每个大蝶形运算
  32.                 for(CntOfBigDieXing = 0;CntOfBigDieXing<NbrOfBigDieXing;CntOfBigDieXing++)
  33.                 {
  34.                         //第三层循环——每个小蝶形运算
  35.                         //蝶形中NbrOfDataInPerDieXing个数的计算,这NbrOfDataInPerDieXing个数又分为(NbrOfDataInPerDieXing/2)个
  36.                         //2-》2的蝶形运算,每个数交叉
  37.                         for(CntOfLittleDieXing = 0;CntOfLittleDieXing<NbrOfLittleDieXingInBigDiexing;CntOfLittleDieXing++)
  38.                         {
  39.                                 //计算出小蝶形算法的第二个初始值的索引
  40.                                 Index1 = CntOfBigDieXing*NbrOfDataInPerBigDieXing+NbrOfDataInPerBigDieXing/2+CntOfLittleDieXing;
  41.                                 Index0 = Index1 - NbrOfLittleDieXingInBigDiexing;

  42. #if (DEBUG == 1)
  43.                                 printf("%d - %d ",Index0,Index1);               
  44. #endif
  45.                                 //旋转因子跟初始值相乘,旋转因子的步进值跟级数有关
  46.                                 //1级——4,二级——2,三级——1,这跟NbrOfBigDieXing是一样的,所以u的索引为CntOfLittleDieXing*NbrOfBigDieXing
  47.                                 ComplexNbrMultip(OriginalBuff[Index1],u[CntOfLittleDieXing*NbrOfBigDieXing],&TempComplexNbr);

  48.                                 //先对小蝶形中的第二个进行减,然后再对第一个进行加
  49.                                 ComplexNbrSub(OriginalBuff[Index0],TempComplexNbr,&OriginalBuff[Index1]);
  50.                                 ComplexNbrPlus(OriginalBuff[Index0],TempComplexNbr,&OriginalBuff[Index0]);
  51.                         }
  52.                 }

  53.                 printf(" ");
  54.         }
  55.         
  56. }
复制代码 QQ截图20160601212102.png (22.06 KB, 下载次数: 1) 下载附件 2016-6-1 21:18 上传

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。