打印
[N32G45x]

快速傅里叶变换

[复制链接]
515|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xiaoyaodz|  楼主 | 2023-12-23 14:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式


#include <stdio.h>
#include <math.h>
#define PI 3.1415926
#define FFT_LENGTH                8
double input[FFT_LENGTH]={1,1,1,1,1,1,1,1};
struct complex1{                //定义一个复数结构体
        double real;        //实部
        double image;        //虚部
};        
//将input的实数结果存放为复数
struct complex1 result_dat[8];
/*
        虚数的乘法
*/
struct complex1 con_complex(struct complex1 a,struct complex1 b){
        struct complex1 temp;
        temp.real=(a.real*b.real)-(a.image*b.image);
        temp.image=(a.image*b.real)+(a.real*b.image);
        return temp;
}
/*
        简单的a的b次方
*/
int mypow(int a,int b){
        int i,sum=a;
        if(b==0)return 1;
        for(i=1;i<b;i++){
                sum*=a;        
        }
        return sum;
}
/*
        简单的求以2为底的正整数
*/
int log2(int n){
        unsigned i=1;
        int sum=1;
        for(i;;i++){
                sum*=2;
                if(sum>=n)break;
        }
        return i;
}
/*
        简单的交换数据的函数
*/
void swap(struct complex1 *a,struct complex1 *b){
        struct complex1 temp;
    temp=*a;
    *a=*b;
    *b=temp;
}
/*
        dat为输入数据的数组
        N为抽样次数  也代表周期  必须是2^N次方
*/
void fft(struct complex1 dat[],unsigned char N){        
        /*最终  dat_buf计算出 当前蝶形运算奇数项与W  乘积
                        dat_org存放上一个偶数项的值
        */
        struct complex1 dat_buf,dat_org;
        /*        L为几级蝶形运算    也代表了2进制的位数
                n为当前级蝶形的需要次数  n最初为N/2 每级蝶形运算后都要/2
                i j为倒位时要用到的自增符号  同时  i也用到了L碟级数   j是计算当前碟级的计算次数
                re_i i_copy均是倒位时用到的变量
                k为当前碟级  cos(2*pi/N*k)的  k   也是e^(-j2*pi/N)*k  的  k
        */
        unsigned char L,i,j,re_i=0,i_copy=0,k=0,fft_flag=1;
        //经过观察,发现每级蝶形运算需要N/2次运算,共运算N/2*log2N  次  
        unsigned char fft_counter=0;
        //在此要进行补2   N必须是2^n   在此略
        //蝶形级数  (L级)
        L=log2(N);        
        //计算每级蝶形计算的次数(这里只是一个初始值)  之后每次要/2
        //n=N/2;
        //对dat的顺序进行倒位
        for(i=1;i<N/2;i++){
                i_copy=i;
                re_i=0;
                for(j=L-1;j>0;j--){
                        //判断i的副本最低位的数字  并且移动到最高位  次高位  ..
                        //re_i为交换的数   每次它的数字是不能移动的 并且循环之后要清0
                        re_i|=((i_copy&0x01)<<j);               
                        i_copy>>=1;
                }
                swap(&dat[i],&dat[re_i]);
        }
        //进行fft计算
        for(i=0;i<L;i++){
               
                fft_flag=1;
                fft_counter=0;
                for(j=0;j<N;j++){
                        if(fft_counter==mypow(2,i)){                //控制隔几次,运算几次,
                                fft_flag=0;
                        }else if(fft_counter==0){                //休止结束,继续运算
                                fft_flag=1;
                        }
                        //当不判断这个语句的时候  fft_flag保持  这样就可以持续运算了
                        if(fft_flag){
                                dat_buf.real=cos((2*PI*k)/(N/mypow(2,L-i-1)));
                                dat_buf.image=-sin((2*PI*k)/(N/mypow(2,L-i-1)));
                                dat_buf=con_complex(dat[j+mypow(2,i)],dat_buf);
                                                                                                //计算 当前蝶形运算奇数项与W  乘积
                                dat_org.real=dat[j].real;
                                dat_org.image=dat[j].image;                //暂存
                                dat[j].real=dat_org.real+dat_buf.real;
                                dat[j].image=dat_org.image+dat_buf.image;               
                                                                                                        //实部加实部   虚部加虚部
                                dat[j+mypow(2,i)].real=dat_org.real-dat_buf.real;
                                dat[j+mypow(2,i)].image=dat_org.image-dat_buf.image;
                                                                                                        //实部减实部        虚部减虚部
                                k++;
                                fft_counter++;
                        }else{
                                fft_counter--;                                //运算几次,就休止几次
                                k=0;
                        }
                }
        }
        
}
void main(){
        int i;
        //先将输入信号转换成复数
        for(i=0;i<FFT_LENGTH;i++){
                result_dat[i].image=0;        
                                                                //输入信号是二维的,暂时不存在复数
                result_dat[i].real=input[i];
                //result_dat[i].real=10;
                                                                //输入信号都为实数
        }
        fft(result_dat,FFT_LENGTH);
        for(i=0;i<FFT_LENGTH;i++){
                input[i]=sqrt(result_dat[i].real*result_dat[i].real+result_dat[i].image*result_dat[i].image);
                //取模
                printf("%lf\n",input[i]);
        }
        while(1);
}


使用特权

评论回复
沙发
丙丁先生| | 2023-12-24 19:07 | 只看该作者
应用场景在哪里?

使用特权

评论回复
板凳
pattywu| | 2023-12-27 15:25 | 只看该作者
分析波形的.
应用场景:
旋转变压器/旋转编码器.

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

36

主题

4744

帖子

2

粉丝