FFT与IFFT算法的C程序实现

来源:本站
导读:目前正在解读《FFT与IFFT算法的C程序实现》的相关信息,《FFT与IFFT算法的C程序实现》是由用户自行发布的知识型内容!下面请观看由(电工技术网 - www.9ddd.net)用户发布《FFT与IFFT算法的C程序实现》的详细说明。
简介:FFT与IFFT算法的C程序实现

1.FFT的发展

有限长序列可以通过离散傅立叶变换(DFT)将其频域也离散化成有限长序列.但其计算量太大,很难实时地处理问题,因此引出了快速算法傅立叶变换(FFT). 1965年,Cooley和Tukey提出了计算离散傅立叶变换(DFT)的快速算法,将DFT的运算量减少了几个数量级。从此,对快速傅立叶变换(FFT)算法的研究便不断深入,数字信号处理这门新兴学科也随FFT的出现和发展而迅速发展。根据对序列分解与选取方法的不同而产生了FFT的多种算法,基本算法是基2DIT和基2DIF。FFT在离散傅立叶反变换、线性卷积和线性相关等方面也有重要应用。

快速傅氏变换(FFT),是离散傅氏变换的快速算法,它是根据离散傅氏变换的奇、偶、虚、实等特性,对离散傅立叶变换的算法进行改进获得的。它对傅氏变换的理论并没有新的发现,但是对于在计算机系统或者说数字系统中应用离散傅立叶变换,可以说是进了一大步。

傅立叶变换是数字信号处理领域一种很重要的算法。要知道傅立叶变换算法的意义,首先要了解傅立叶原理的意义。傅立叶原理表明:任何连续测量的时序或信号,都可以表示为不同频率的正弦波信号的无限叠加。而根据该原理创立的傅立叶变换算法利用直接测量到的原始信号,以累加方式来计算该信号中不同正弦波信号的频率、振幅和相位。和傅立叶变换算法对应的是反傅立叶变换算法。该反变换从本质上说也是一种累加处理,这样就可以将单独改变的正弦波信号转换成一个信号。

因此,可以说,傅立叶变换将原来难以处理的时域信号转换成了易于分析的频域信号(信号的频谱),可以利用一些工具对这些频域信号进行处理、加工。最后还可以利用傅立叶反变换将这些频域信号转换成时域信号。

从现代数学的眼光来看,傅立叶变换是一种特殊的积分变换。它能将满足一定条件的某个函数表示成正弦基函数的线性组合或者积分。在不同的研究领域,傅立叶变换具有多种不同的变体形式,如连续傅立叶变换和离散傅立叶变换。C语言为其提供软件支持,FFT与IFFT均可通过C语言来实现。

2.运用

1.卷积

卷积是滤波网络对信号响应的术语,即用卷积积分来描述滤波网络对冲击函数信号的反应。若x(t)为信号,h(t)为响应,则卷积积分表示如下:

h(t)·x(t) = ∫x(τ)h(t-τ)dτ, 区间:-∽~+∽

每一个卷积点是信号函数与反转和平移后的网络函数的乘积中的区域。

相关

相关是用于小信号噪声检测的一种方法。如果有已知信号与一个噪声波形相关,用这个方法可以检测出来,有非零的结果表示发现了相关性,结果越明显,相关性越大。其在形式上与卷积积分相似,如下:

z(t) = ∫x(τ)h(t+τ)dt, 区间:-∽~+∽

自相关是用来描述一个信号与它自己的相关程度,其值为信号的PSD,即功率谱密度。

2.滤波

这可能是FFT最广泛的应用了,它使对波形的频率分量滤波变得十分简单。比如对采样信号进行FFT后,干掉不需要的频率分量,再进行FFT反变换,就得到滤波后的期望信号。

3.信号分析

比如电力监控系统的谐波分析,就需要对采样数据进行FFT运算,然后通过液晶屏或其它人机界面重新绘画出来,以方便技术人员掌握电力的质量。

小结:

傅立叶变换在目前的相关电子产品中用得非常广泛,可以说,它是描述函数的另一种语言。掌握傅立叶变换,学会在空域和频域中同时思考问题,很多时候可以让我们使用简单的方法来解决复杂的问题。

3.FFT结果的物理意义

FFT是离散傅立叶变换的快速算法,可以将一个信号变换到频域。有些信号在时域上是很难看出什么特征的,但是如果变换到频域之后,就很容易看出特征了。这就是很多信号分析采用FFT变换的原因。另外,FFT可以将一个信号的频谱提取出来,这在频谱分析方面也是经常用的。

虽然很多人都知道FFT是什么,可以用来做什么,怎么去做,但是却不知道FFT之后的结果是什意思、如何决定要使用多少点来做FFT。

一个模拟信号,经过ADC采样之后,就变成了数字信号。采样定理告诉我们,采样频率要大于信号频率的两倍,这些我就不在此罗嗦了。

采样得到的数字信号,就可以做FFT变换了。N个采样点,经过FFT之后,就可以得到N个点的FFT结果。为了方便进行FFT运算,通常N取2的整数次方。

假设采样频率为Fs,信号频率F,采样点数为N。那么FFT之后结果就是一个为N点的复数。每一个点就对应着一个频率点。这个点的模值,就是该频率值下的幅度特性。具体跟原始信号的幅度有什么关系呢?假设原始信号的峰值为A,那么FFT的结果的每个点(除了第一个点直流分量之外)的模值就是A的N/2倍。 而第一个点就是直流分量,它的模值就是直流分量的N倍。而每个点的相位呢,就是在该频率下的信号的相位。第一个点表示直流分量(即0Hz),而最后一个点 N的再下一个点(实际上这个点是不存在的,这里是假设的第N+1个点,可以看做是将第一个点分做两半分,另一半移到最后)则表示采样频率Fs,这中间被 N-1个点平均分成N等份,每个点的频率依次增加。例如某点n所表示的频率为:FFT与IFFT算法的C程序实现。由上面的公式可以看出,Fn所能分辨到频率为 Fs/N,如果采样频率Fs为1024Hz,采样点数为1024点,则可以分辨到1Hz。1024Hz的采样率采样1024点,刚好是1秒,也就是说,采样1秒时间的信号并做FFT,则结果可以分析到1Hz,如果采样2秒时间的信号并做FFT,则结果可以分析到0.5Hz。如果要提高频率分辨力,则必须增加采样点数,也即采样时间。频率分辨率和采样时间是倒数关系。假设FFT之后某点n用复数a+bi表示,那么这个复数的模就是FFT与IFFT算法的C程序实现,相位就是FFT与IFFT算法的C程序实现。根据以上的结果,就可以计算出n点(n≠1,且n<=N/2)对应的信号的表达式为:FFT与IFFT算法的C程序实现,即FFT与IFFT算法的C程序实现。对于n=1点的信号,是直流分量,幅度即为A1/N。由于FFT结果的对称性,通常我们只使用前半部分的结果,即小于采样频率一半的结果。

假设采样频率为Fs,采样点数为N,做FFT之后,某一点n(n从1开始)表示的频率为:Fn=(n-1)*Fs/N;该点的模值除以N/2就是对应该频率下的信号的幅度(对于直流信号是除以N);该点的相位即是对应该频率下的信号的相位。相位的计算可用函数atan2(b,a)计算。atan2(b,a)是求坐标为(a,b)点的角度值,范围从-pi到pi。要精确到xHz,则需要采样长度为1/x秒的信号,并做FFT。要提高频率分辨率,就需要增加采样点数,这在一些实际的应用中是不现实的,需要在较短的时间内完成分析。解决这个问题的方法有频率细分法,比较简单的方法是采样比较短时间的信号,然后在后面补充一定数量的0,使其长度达到需要的点数,再做FFT,这在一定程度上能够提高频率分辨力。

具体的频率细分法可参考相关文献

程序如下:

le=pow(2,l);

// 这里用的是L而不是1//

lei=le/2 ;

pi=3.14159 ;

v.real=1.0 ;

v.imag=0.0 ;

w.real=cos(pi/lei);

w.imag=-sin(pi/lei);

for(j=1;j<=lei;j++)

{

/*double p=pow(2,m-l)*j;

double ps=2*pi/N*p;

w.real=cos(ps);

w.imag=-sin(ps);*/

for(i=j;i<=N;i=i+le)

{

/* w.real=cos(ps);

w.imag=-sin(ps);*/

ip=i+lei ;

t=EE(xin[ip],v);

xin[ip].real=xin[i].real-t.real ;

xin[ip].imag=xin[i].imag-t.imag ;

xin[i].real=xin[i].real+t.real ;

xin[i].imag=xin[i].imag+t.imag ;

}

v=EE(v,w);

}

}

}

return ;

}

/*****************main programe********************/

#include<math.h>

#include<stdio.h>

#include<stdlib.h>

#include "typedef.h"

float result[257];

struct compx s[257];

int Num=256 ;

const float pp=3.14159 ;

main()

{

int i=1 ;

for(;i<0x101;i++)

{

s[i].real=sin(pp*i/32);

s[i].imag=0 ;

}

FFT(s,Num);

for(i=1;i<0x101;i++)

{

result[i]=sqrt(pow(s[i].real,2)+pow(s[i].imag,2));

}

}

4、DSP板调试结果之波形及波形分析

DSP板有多种调试方法,下面使用的一种为观测其示波器波形的方法,通过波形,我们可以看出此板子的性能。使用通用定时器Timer1/2/3/4产生PWM,选择连续计数模式可以产生如下图所示的非对称PWM波形选择连续增/减计数模式可以产生中心或对称PWM波形如下:

FFT与IFFT算法的C程序实现

图 4.5PWM波形

同样,采用连续增计数模式可以产生一对带有死区的互补的非对称PWM波形FFT与IFFT算法的C程序实现

图 4.6 非对称PWM波形

采用连续增/减计数模式可以产生一对带有死区的互补的对称PWM波形FFT与IFFT算法的C程序实现

图 4.7互补的对称PWM波形

FFT与IFFT算法的C程序实现

图 4.8互补的对称PWM波形

实现的方法如下:

(1)采用通用定时器Timer1和Timer2产生两路PWM波形;

(2)为了产生对称波形,使两个定时器都工作于连续增/减计数模式;

(3)从上图可以看出,S1的上升延和S2的上升延始终相差半个Ts,及半个周期,为了实现相移,可以让T1先开始计时工作,当T1到达第一个周期中断的时候打开T2,让T2也开始工作,同时需要去使能T1中断,或者通过置标志位等方法使得以后T1周期中断的时候不会再去打开T2定时器。这样就可以使的T1和T2输出的波形满足上图的要求,即既是互补,又是导通时间对称的PWM波形,只要占空比不足50%,就相当于留有一段死区时间。可以参看下面的示意图4.9所示。

FFT与IFFT算法的C程序实现

图4.9 波形图

5 结论

5.1工作总结

通过本次论文设计的学习,可使我掌握有关快速傅立叶变换与快速傅立叶反变换的基本概念、基础理论极其典型的算法通过C程序语言实现。通过该系列实验教学与实践,深入的了解了按时间抽选的基2FFT算法、按频率抽选的基2FFT算法、离散IFFT的快速计算方法、分裂基FFT算法、并分析算法的物理意义;了解快速傅立叶变换的基本原理、VC6.0软件编程环境及构成DSP的典型的应用,为将来的研究和应用打下良好的基础。通过自己对VC6.0对FFT算法的实现的流程有了比较深刻的体会,同时也了解了一般软件设计的过程。在设计过程中碰到了很多的问题,通过这些问题,使自己分的析问题和解决问题的能力得到了较大的提高。

5.2技术展望

FFT/IFFT是时域信号与频域信号之间转换的基本运算,是数字信号处理的核心工具之一,因此,它广泛地应用于许多领域。在数字化的今天,对数字信号处理的速度、精度和实时性要求不断提高。当今,FFT算法在国外的发展已经相当成熟。在数字信号处理方面,国外的FFT算法处于领先地位,尤其是DSP芯片。目前,FFT算法通过C程序的实现为国际上的很多领域的发展提供了便利,也为其他领域的相关发展提供了应用基础。由于国际上的芯片处理技术的飞速发展,使得应用VC++6.0操作环境,大大提高了数字信号处理应用系统关于FFT算法的可操作性和可靠性。这项工作对于实时数字信号应用系统的处理具有举足轻重作用。

提醒:《FFT与IFFT算法的C程序实现》最后刷新时间 2024-03-14 01:19:02,本站为公益型个人网站,仅供个人学习和记录信息,不进行任何商业性质的盈利。如果内容、图片资源失效或内容涉及侵权,请反馈至,我们会及时处理。本站只保证内容的可读性,无法保证真实性,《FFT与IFFT算法的C程序实现》该内容的真实性请自行鉴别。