1. #include "uart.h"
    2. #include "fft.h"
    3. void main()
    4. {
    5. u8 Freq=0; //峰值对应频率
    6. //从y=200*sin(2*pi*40*t)中取得数据点
    7. s16 code DATA[128]={0,118 , -190 , 190 , -118 , 0 , 118 , -190 ,
    8. 190 ,-118 , 0 , 118 , -190 , 190 , -118, 0 ,
    9. 118 ,-190 , 190 , -118 , 0 , 118 , -190 , 190 ,
    10. -118,0 ,118 , -190 , 190 , -118, 0 , 118 ,
    11. -190 , 190 , -118 , 0 , 118 , -190 , 190 , -118 ,
    12. 0 , 118 , -190 , 190 , -118, 0 , 118 , -190 ,
    13. 190 , -118 , 0 , 118 , -190 , 190 , -118 , 0 ,
    14. 118 , -190 , 190 , -118 , 0 , 118 , -190 , 190 ,
    15. -118 , 0 , 118 , -190 , 190 , -118 , 0 , 118 ,
    16. -190 , 190 , -118 , 0 , 118 , -190 , 190 , -118 ,
    17. 0 , 118 , -190 , 190 , -118 , 0 , 118 , -190 ,
    18. 190 , -118 , 0 , 118 , -190 , 190 , -118 , 0 ,
    19. 118 , -190 , 190 , -118 , 0 , 118 , -190 , 190 ,
    20. -118 , 0 , 118 , -190 , 190 , -118 , 0 , 118 ,
    21. -190 , 190 , -118 , 0 , 118 , -190 , 190 , -118,
    22. 0 , 118 , -190, 190 , -118, 0 , 118 , -190 };
    23. u8 ii,Max_Place=0; //用Max_Place保存频谱中最大峰值在数组中的位置
    24. float Out_abs[NN/2]; //用于保存模值,因为频谱图关于Fs/2对称,所以只求一半
    25. complex y[NN];
    26. for (ii = 0; ii < NN; ++ii)
    27. {
    28. y[ii].real = DATA[ii];
    29. y[ii].imag = 0;
    30. }
    31. fft(NN, y); //FFT运算
    32. c_abs(y, Out_abs, NN/2); //求模
    33. Max_Place=Mag(Out_abs); //求最大模所在位置
    34. Freq=(Max_Place-1)*Fs/(NN-1); //得到最大模对应频率
    35. UartInit();
    36. printf("Freq: %bd,max_place: %bd\r\n",Freq,Max_Place);
    37. while(1)
    38. {
    39. }
    40. }
    1. #ifndef __FFT_H__
    2. #define __FFT_H__
    3. typedef struct complex //复数类型
    4. {
    5. float real; //实部
    6. float imag; //虚部
    7. }complex;
    8. #define PI 3.1415926535
    9. #define NN 16 //采样点数
    10. #define Fs 100 //采样频率
    11. #define u8 unsigned char
    12. #define s8 signed char
    13. #define u16 unsigned int
    14. #define s16 signed int
    15. ///////////////////////////////////////////In file fft.c
    16. void c_plus(complex a,complex b,complex *c);//复数加
    17. void c_mul(complex a,complex b,complex *c) ;//复数乘
    18. void c_sub(complex a,complex b,complex *c); //复数减法
    19. void fft(int N,complex f[]);//傅立叶变换 输出也存在数组f
    20. void c_abs(complex f[],float out[],int n);//复数数组取模
    21. u16 Mag(float outRes[]); //求最大值所在位置
    22. ////////////////////////////////////////////
    23. #endif
    1. #include "math.h"
    2. #include "fft.h"
    3. //精度0.0001弧度
    4. void c_abs(complex f[],float out[],int n)
    5. {
    6. int i = 0;
    7. float t;
    8. for(i=0;i<n;i++)
    9. {
    10. t = f[i].real * f[i].real + f[i].imag * f[i].imag;
    11. out[i] = sqrt(t);
    12. }
    13. }
    14. void c_plus(complex a,complex b,complex *c)
    15. {
    16. c->real = a.real + b.real;
    17. c->imag = a.imag + b.imag;
    18. }
    19. void c_sub(complex a,complex b,complex *c)
    20. {
    21. c->real = a.real - b.real;
    22. c->imag = a.imag - b.imag;
    23. }
    24. void c_mul(complex a,complex b,complex *c)
    25. {
    26. c->real = a.real * b.real - a.imag * b.imag;
    27. c->imag = a.real * b.imag + a.imag * b.real;
    28. }
    29. void Wn_i(int n,int i,complex *Wn)
    30. {
    31. Wn->real = cos(2*PI*i/n);
    32. Wn->imag = -sin(2*PI*i/n);
    33. }
    34. //傅里叶变化
    35. void fft(int N,complex f[])
    36. {
    37. complex t,wn;//中间变量
    38. int i,j,k,m,n,l,r,M;
    39. int la,lb,lc;
    40. /*----计算分解的级数M=log2(N)----*/
    41. for(i=N,M=1;(i=i/2)!=1;M++);
    42. /*----按照倒位序重新排列原信号----*/
    43. for(i=1,j=N/2;i<=N-2;i++)
    44. {
    45. if(i<j)
    46. {
    47. t=f[j];
    48. f[j]=f[i];
    49. f[i]=t;
    50. }
    51. k=N/2;
    52. while(k<=j)
    53. {
    54. j=j-k;
    55. k=k/2;
    56. }
    57. j=j+k;
    58. }
    59. /*----FFT算法----*/
    60. for(m=1;m<=M;m++)
    61. {
    62. la=pow(2,m); //la=2^m代表第m级每个分组所含节点数
    63. lb=la/2; //lb代表第m级每个分组所含碟形单元数
    64. //同时它也表示每个碟形单元上下节点之间的距离
    65. /*----碟形运算----*/
    66. for(l=1;l<=lb;l++)
    67. {
    68. r=(l-1)*pow(2,M-m);
    69. for(n=l-1;n<N-1;n=n+la) //遍历每个分组,分组总数为N/la
    70. {
    71. lc=n+lb; //n,lc分别代表一个碟形单元的上、下节点编号
    72. Wn_i(N,r,&wn);//wn=Wnr
    73. c_mul(f[lc],wn,&t);//t = f[lc] * wn复数运算
    74. c_sub(f[n],t,&(f[lc]));//f[lc] = f[n] - f[lc] * Wnr
    75. c_plus(f[n],t,&(f[n]));//f[n] = f[n] + f[lc] * Wnr
    76. }
    77. }
    78. }
    79. }
    80. u16 Mag(float outRes[])
    81. {
    82. u8 i=1;
    83. u8 max,place;
    84. max=outRes[i];
    85. place=i;
    86. for(i=2;i<NN/2;i++)
    87. {
    88. if(outRes[i]>max)
    89. {
    90. max=outRes[i];
    91. place=i;
    92. }
    93. }
    94. return place;
    95. }