[N32G45x] 快速傅里叶变换

[复制链接]
 楼主| xiaoyaodz 发表于 2023-12-23 14:36 | 显示全部楼层 |阅读模式


  1. #include <stdio.h>
  2. #include <math.h>
  3. #define PI 3.1415926
  4. #define FFT_LENGTH                8
  5. double input[FFT_LENGTH]={1,1,1,1,1,1,1,1};
  6. struct complex1{                //定义一个复数结构体
  7.         double real;        //实部
  8.         double image;        //虚部
  9. };        
  10. //将input的实数结果存放为复数
  11. struct complex1 result_dat[8];
  12. /*
  13.         虚数的乘法
  14. */
  15. struct complex1 con_complex(struct complex1 a,struct complex1 b){
  16.         struct complex1 temp;
  17.         temp.real=(a.real*b.real)-(a.image*b.image);
  18.         temp.image=(a.image*b.real)+(a.real*b.image);
  19.         return temp;
  20. }
  21. /*
  22.         简单的a的b次方
  23. */
  24. int mypow(int a,int b){
  25.         int i,sum=a;
  26.         if(b==0)return 1;
  27.         for(i=1;i<b;i++){
  28.                 sum*=a;        
  29.         }
  30.         return sum;
  31. }
  32. /*
  33.         简单的求以2为底的正整数
  34. */
  35. int log2(int n){
  36.         unsigned i=1;
  37.         int sum=1;
  38.         for(i;;i++){
  39.                 sum*=2;
  40.                 if(sum>=n)break;
  41.         }
  42.         return i;
  43. }
  44. /*
  45.         简单的交换数据的函数
  46. */
  47. void swap(struct complex1 *a,struct complex1 *b){
  48.         struct complex1 temp;
  49.     temp=*a;
  50.     *a=*b;
  51.     *b=temp;
  52. }
  53. /*
  54.         dat为输入数据的数组
  55.         N为抽样次数  也代表周期  必须是2^N次方
  56. */
  57. void fft(struct complex1 dat[],unsigned char N){        
  58.         /*最终  dat_buf计算出 当前蝶形运算奇数项与W  乘积
  59.                         dat_org存放上一个偶数项的值
  60.         */
  61.         struct complex1 dat_buf,dat_org;
  62.         /*        L为几级蝶形运算    也代表了2进制的位数
  63.                 n为当前级蝶形的需要次数  n最初为N/2 每级蝶形运算后都要/2
  64.                 i j为倒位时要用到的自增符号  同时  i也用到了L碟级数   j是计算当前碟级的计算次数
  65.                 re_i i_copy均是倒位时用到的变量
  66.                 k为当前碟级  cos(2*pi/N*k)的  k   也是e^(-j2*pi/N)*k  的  k
  67.         */
  68.         unsigned char L,i,j,re_i=0,i_copy=0,k=0,fft_flag=1;
  69.         //经过观察,发现每级蝶形运算需要N/2次运算,共运算N/2*log2N  次  
  70.         unsigned char fft_counter=0;
  71.         //在此要进行补2   N必须是2^n   在此略
  72.         //蝶形级数  (L级)
  73.         L=log2(N);        
  74.         //计算每级蝶形计算的次数(这里只是一个初始值)  之后每次要/2
  75.         //n=N/2;
  76.         //对dat的顺序进行倒位
  77.         for(i=1;i<N/2;i++){
  78.                 i_copy=i;
  79.                 re_i=0;
  80.                 for(j=L-1;j>0;j--){
  81.                         //判断i的副本最低位的数字  并且移动到最高位  次高位  ..
  82.                         //re_i为交换的数   每次它的数字是不能移动的 并且循环之后要清0
  83.                         re_i|=((i_copy&0x01)<<j);               
  84.                         i_copy>>=1;
  85.                 }
  86.                 swap(&dat[i],&dat[re_i]);
  87.         }
  88.         //进行fft计算
  89.         for(i=0;i<L;i++){
  90.                
  91.                 fft_flag=1;
  92.                 fft_counter=0;
  93.                 for(j=0;j<N;j++){
  94.                         if(fft_counter==mypow(2,i)){                //控制隔几次,运算几次,
  95.                                 fft_flag=0;
  96.                         }else if(fft_counter==0){                //休止结束,继续运算
  97.                                 fft_flag=1;
  98.                         }
  99.                         //当不判断这个语句的时候  fft_flag保持  这样就可以持续运算了
  100.                         if(fft_flag){
  101.                                 dat_buf.real=cos((2*PI*k)/(N/mypow(2,L-i-1)));
  102.                                 dat_buf.image=-sin((2*PI*k)/(N/mypow(2,L-i-1)));
  103.                                 dat_buf=con_complex(dat[j+mypow(2,i)],dat_buf);
  104.                                                                                                 //计算 当前蝶形运算奇数项与W  乘积
  105.                                 dat_org.real=dat[j].real;
  106.                                 dat_org.image=dat[j].image;                //暂存
  107.                                 dat[j].real=dat_org.real+dat_buf.real;
  108.                                 dat[j].image=dat_org.image+dat_buf.image;               
  109.                                                                                                         //实部加实部   虚部加虚部
  110.                                 dat[j+mypow(2,i)].real=dat_org.real-dat_buf.real;
  111.                                 dat[j+mypow(2,i)].image=dat_org.image-dat_buf.image;
  112.                                                                                                         //实部减实部        虚部减虚部
  113.                                 k++;
  114.                                 fft_counter++;
  115.                         }else{
  116.                                 fft_counter--;                                //运算几次,就休止几次
  117.                                 k=0;
  118.                         }
  119.                 }
  120.         }
  121.         
  122. }
  123. void main(){
  124.         int i;
  125.         //先将输入信号转换成复数
  126.         for(i=0;i<FFT_LENGTH;i++){
  127.                 result_dat[i].image=0;        
  128.                                                                 //输入信号是二维的,暂时不存在复数
  129.                 result_dat[i].real=input[i];
  130.                 //result_dat[i].real=10;
  131.                                                                 //输入信号都为实数
  132.         }
  133.         fft(result_dat,FFT_LENGTH);
  134.         for(i=0;i<FFT_LENGTH;i++){
  135.                 input[i]=sqrt(result_dat[i].real*result_dat[i].real+result_dat[i].image*result_dat[i].image);
  136.                 //取模
  137.                 printf("%lf\n",input[i]);
  138.         }
  139.         while(1);
  140. }


丙丁先生 发表于 2023-12-24 19:07 来自手机 | 显示全部楼层
应用场景在哪里?
pattywu 发表于 2023-12-27 15:25 | 显示全部楼层
分析波形的.
应用场景:
旋转变压器/旋转编码器.
您需要登录后才可以回帖 登录 | 注册

本版积分规则

36

主题

4965

帖子

2

粉丝
快速回复 返回顶部 返回列表