1、 目 录第1章 引言.2第2章 FFT算法简介.22.1 离散傅里叶变换DFT.22.2 快速傅里叶变换FFT.2第3章FFT算法的DSP实现.53.1 实现数据的比特反转.53.2 实现N点复数FFT.53.3 输出FFT结果.6第4章 系统开发平台与环境.64.1 CCS开发环境.64.2SEED-DEC2812开发试验箱.6第5章 软件设计.75.1流程图.75.2 源程序.8 第6章 系统仿真.14 第七章 总结.19参考文献.191.引言 傅里叶变换是将信号从时域变换到频域的一种变换形式,是信号处理领域中一种重要的分析工具。离散傅里叶变换(DFT)是连续傅里叶变换在离散系统中的表现形
2、式。由于DFT的计算量很大,因此在很长一段时间内使其应用受到很大的限制。20世纪60年代由Cooley和Tukey提出了快速傅里叶变换(FFT)算法,它是快速计算DFT的一种高效方法,可以明显地降低运算量,大大地提高DFT的运算速度,从而使DFT在实际中得到了广泛的应用,已成为数字信号处理最为重要的工具之一。DSP芯片的出现使FFT的实现变得更加方便。由于多数的DSP芯片都能在单指令周期内完成乘法累加运算,而且还提供了专门的FFT指令(如实现FFT算法所必需的比特反转等),使得FFT算法在DSP芯片上实现的速度更快。本节首先简要介绍FFT算法的基本原理,然后介绍FFT算法的DSP实现。2.FF
3、T算法的简介快速傅里叶变换(FFT)是一种高效实现离散傅里叶变换(DFT)的快速算法,是数字信号处理中最为重要的工具之一,它在声学,语音,电信和信号处理等领域有着广泛的应用。2.1离散傅里叶变换DFT对于长度为N的有限长序列x(n),它的离散傅里叶变换(DFT)为 (1)式中, ,称为旋转因子或蝶形因子。 从DFT的定义可以看出,在x(n)为复数序列的情况下,对某个k值,直接按(1)式计算X(k) 只需要N次复数乘法和(N-1)次复数加法。因此,对所有N个k值,共需要N2次复数乘法和N(N-1)次复数加法。对于一些相当大有N值(如1024点)来说,直接计算它的DFT所需要的计算量是很大的,因此
4、DFT运算的应用受到了很大的限制。2.2快速傅里叶变换FFT旋转因子WN 有如下的特性。对称性: 周期性:利用这些特性,既可以使DFT中有些项合并,减少了乘法积项,又可以将长序列的DFT分解成几个短序列的DFT。FFT就是利用了旋转因子的对称性和周期性来减少运算量的。FFT的算法是将长序列的DFT分解成短序列的DFT。例如:N为偶数时,先将N点的DFT分解为两个N/2点的DFT,使复数乘法减少一半:再将每个N/2点的DFT分解成N/4点的DFT,使复数乘又减少一半,继续进行分解可以大大减少计算量。最小变换的点数称为基数,对于基数为2的FFT算法,它的最小变换是2点DFT。一般而言,FFT算法分
5、为按时间抽取的FFT(DIT)和按频率抽取的(DIF FFT)两大类。IF FFT算法是在时域内将每一级输入序列依次按奇偶分成个短序列进行计算。而DIF FFT算法是在频域内将每一级输入序列依次奇偶分成个短序列进行计算。两者的区别是旋转因子出现的位置不同,得算法是一样的。在DIF FFT算法中,旋转因子出现在输入端,而在DIF FFT算法中它出现在输入端。假定序列x(n)的点数N是2的幂,按照DIF FFT算法可将其分为偶序列和奇序列。偶序列: 奇序列:则x(n)的DFT表示为 由于 ,则(3)式可表示为 式中, 和分别为和的N/2的DFT。 由于对称性,则。因此,N点可分为两部分:前半部分:
6、 (4)后半部分: (5)从式(4)和式(5)可以看出,只要求出0N/2-1区间和的值,就可求出0N-1区间的N点值。以同样的方式进行抽取,可以求得N/4点的DFT,重复抽取过程,就可以使N点的DFT用上组2点的 DFT来计算,这样就可以大减少运算量。基2 DIF FFT的蝶形运算如图(a)所示。设蝶形输入为和,输出为和,则有 (6) (7)在基数为2的FFT中,设N=2M,共有M级运算,每级有N/2个2点FFT蝶形运算,因此,N点FFT总共有个蝶形运算。 -1 图(a) 基2 DIF FFT的蝶形运算例如:基数为2的FFT,当N=8时,共需要3级,12个基2 DIT FFT的蝶形运算。其信号
7、流程如图(b)所示。x(0) x(0) WN0x(4) x(1) -1 WN0x(2) x(2) -1 WN0 WN2x(6) x(3) -1 -1 WN0x(1) x(4) -1 WN0 WN1x(5) x(5) -1 -1 WN0 WN2x(3) x(6) -1 -1 WN0 WN2 WN3x(7) x(7) -1 -1 -1 图(b) 8点基2 DIF FFT蝶形运算从图(b)可以看出,输入是经过比特反转的倒位序列,称为位码倒置,其排列顺序为。输出是按自然顺序排列,其顺序为。3.FFT算法的DSP实现DSP芯片的出现使FFT的实现方法变得更为方便。由于大多数DSP芯片都具有在单指令周期内
8、完成乘法累加操作,并且提供了专门的FFT指令,使得FFT算法在DSP芯片实现的速度更快。FFT算法可以分为按时间抽取FFT (DIF FFT)和按频率抽取FFT (DIF FFT)两大类,输入也有实数和复数之分,一般情况下,都假定输入序列为复数。下面以N复数点FFT算法为例,介绍用DSP芯片实现的方法。实现FFT算法主要分为三步:3.1实现输入数据的比特反转输入数据的比特反转实际上就是将输入数据进行位码倒置,以便在整个运算后的输出序列是一个自然序列。在用汇编指令进行位码倒置是,使用位码倒置寻址可以大大担高程序执行速度和使用存储器的效率。在这种寻址方式下,AR0存放的整数N是FFT点的一半,一个
9、辅助寄存器指向一个数据存放的章元。当使用位码倒置寻址将AR0加到辅助寄存器时,地址将以位码倒置的方式产生。3.2实现N点复数FFTN点复数FFT算法的实现可分为三个功能块,即第一级蝶形运算,第二蝶形运算,第三级至级蝶形运算。对于任何一个2的整数幂N=2M,总可以通过M次分解最后成为2点的DFT计算。通过这样的M次分解,可构成M(即)级迭代运算完成。3.3输出FFT结果四.系统开发平台与环境4.1 CCS开发环境CCS提供了配置、建立、调试、跟踪和分析程序的工具,它便于实时、嵌入式信号处理程序的编制和测试,它能够加速开发进程,提高工作效率。CCS提供了基本的代码生成工具,它们具有一系列的调试、分
10、析能力。CCS支持如下图1.1所示的开发周期的所有阶段。图 1.14.2 SEED-DEC2812开发实验箱 SEED-DECxxxx系列嵌入式DSP开发板本着模块化、总线型、开放式、系列化的设计思想,采用统一的系统结构、模块结构和机械结构,以多种典型DSP处理器构成具有标准总线和相同物理尺寸的高性能嵌入式DSP开发板。SEED-DEC2812 嵌入式DSP开发板原理框图如图1.2所示:图 1.2五.软件设计5.1程序流程图开始初始化工作变量调用波形发生子程序产生波形(3个正弦波)调用FFT子程序计算功率谱波形发生计算步长用标准的C的sin函数计算当前波形值结束开始按照编码逆序排列输入序列用蝶
11、形算法计算计算功率谱返回计算结果5.2源程序#include DSP281x_Device.h / DSP281x Headerfile Include File#include DSP281x_Examples.h / DSP281x Examples Include File#include f2812a.h#includemath.h#define PI 3.1415926#define SAMPLENUMBER 128#include DSP281x_Device.h / DSP281x Headerfile Include File#include DSP281x_Examples.
12、h / DSP281x Examples Include File/ Prototype statements for functions found within this file.interrupt void adc_isr(void);/ Global variables used in this example:void admain();void InitForFFT();void MakeWave();/void FFT(float dataRSAMPLENUMBER,float dataISAMPLENUMBER);Uint16 LoopCount;Uint16 Convers
13、ionCount;Uint16 Voltage11024;Uint16 Voltage21024;Uint16 nMixing1024;int INPUTSAMPLENUMBER,DATASAMPLENUMBER;float fWaveRSAMPLENUMBER,fWaveISAMPLENUMBER,wSAMPLENUMBER;float sin_tabSAMPLENUMBER,cos_tabSAMPLENUMBER;admain(void) InitSysCtrl();/初始化cpu DINT;/关中断 InitPieCtrl();/初始化pie寄存器 IER = 0x0000;/禁止所有的
14、中断 IFR = 0x0000; InitPieVectTable();/初始化pie中断向量表 / Interrupts that are used in this example are re-mapped to/ ISR functions found within this file. EALLOW; / This is needed to write to EALLOW protected register PieVectTable.ADCINT = &adc_isr; EDIS; / This is needed to disable write to EALLOW protect
15、ed registers AdcRegs.ADCTRL1.bit.RESET = 1;/ Reset the ADC moduleasm( RPT #10 | NOP);/ Must wait 12-cycles (worst-case) AdcRegs.ADCTRL3.all = 0x00C8;/ first power-up ref and bandgap circuits AdcRegs.ADCTRL3.bit.ADCBGRFDN = 0x3;/ Power up bandgap/reference circuitry AdcRegs.ADCTRL3.bit.ADCPWDN = 1;/
16、Power up rest of ADC/ Enable ADCINT in PIE PieCtrlRegs.PIEIER1.bit.INTx6 = 1; IER |= M_INT1; / Enable CPU Interrupt 1 EINT; / Enable Global interrupt INTM ERTM; / Enable Global realtime interrupt DBGM LoopCount = 0; ConversionCount = 0; / Configure ADC AdcRegs.ADCMAXCONV.all = 0x0001; / Setup 2 conv
17、s on SEQ1 AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0; / Setup ADCINA3 as 1st SEQ1 conv. AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x1; / Setup ADCINA2 as 2nd SEQ1 conv. AdcRegs.ADCTRL2.bit.EVA_SOC_SEQ1 = 1; / Enable EVASOC to start SEQ1 AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1; / Enable SEQ1 interrupt (every EOS)/ C
18、onfigure EVA/ Assumes EVA Clock is already enabled in InitSysCtrl(); EvaRegs.T1CMPR = 0x0080; / Setup T1 compare value EvaRegs.T1PR = 0x10; / Setup period register EvaRegs.GPTCONA.bit.T1TOADC = 1; / Enable EVASOC in EVA EvaRegs.T1CON.all = 0x1042; / Enable timer 1 compare (upcount mode)/ Wait for AD
19、C interrupt while(1) LoopCount+; interrupt void adc_isr(void) Voltage1ConversionCount = AdcRegs.ADCRESULT0 4; Voltage2ConversionCount = AdcRegs.ADCRESULT1 4; nMixingConversionCount=Voltage1ConversionCount+Voltage2ConversionCount; / If 40 conversions have been logged, start over if(ConversionCount =
20、1023) ConversionCount = 0; else ConversionCount+; / Reinitialize for next ADC sequence AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; / Reset SEQ1 AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1; / Clear INT SEQ1 bit PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; / Acknowledge interrupt to PIE return;void FFT(float dataRSAMPLENUMBE
21、R,float dataISAMPLENUMBER)int x0,x1,x2,x3,x4,x5,x6,xx;int i,j,k,b,p,L;float TR,TI,temp;/* following code invert sequence */for ( i=0;iSAMPLENUMBER;i+ )x0=x1=x2=x3=x4=x5=x6=0;x0=i&0x01; x1=(i/2)&0x01; x2=(i/4)&0x01; x3=(i/8)&0x01;x4=(i/16)&0x01; x5=(i/32)&0x01; x6=(i/64)&0x01;xx=x0*64+x1*32+x2*16+x3*
22、8+x4*4+x5*2+x6;dataIxx=dataRi;for ( i=0;iSAMPLENUMBER;i+ )dataRi=dataIi; dataIi=0; /* following code FFT */for ( L=1;L0 ) b=b*2; i-; /* b= 2(L-1) */for ( j=0;j0 ) /* p=pow(2,7-L)*j; */p=p*2; i-;p=p*j;for ( k=j;k128;k=k+2*b ) /* for (3) */TR=dataRk; TI=dataIk; temp=dataRk+b;dataRk=dataRk+dataRk+b*cos
23、_tabp+dataIk+b*sin_tabp;dataIk=dataIk-dataRk+b*sin_tabp+dataIk+b*cos_tabp;dataRk+b=TR-dataRk+b*cos_tabp-dataIk+b*sin_tabp;dataIk+b=TI+temp*sin_tabp-dataIk+b*cos_tabp; /* END for (3) */ /* END for (2) */ /* END for (1) */for ( i=0;iSAMPLENUMBER/2;i+ ) wi=sqrt(dataRi*dataRi+dataIi*dataIi); /* END FFT
24、*/main()int i;InitForFFT();MakeWave();for ( i=0;iSAMPLENUMBER;i+ )fWaveRi=INPUTi;fWaveIi=0.0f;wi=0.0f;FFT(fWaveR,fWaveI);for ( i=0;iSAMPLENUMBER;i+ )DATAi=wi;while ( 1 );/ break pointvoid InitForFFT()int i;for ( i=0;iSAMPLENUMBER;i+ )sin_tabi=sin(PI*2*i/SAMPLENUMBER);cos_tabi=cos(PI*2*i/SAMPLENUMBER
25、);void MakeWave()int i;for ( i=0;iSAMPLENUMBER;i+ )admain();INPUTi=Voltage1ConversionCount+Voltage2ConversionCount*3;六.系统仿真(1)启动CCS,在CCS中建立一个C源文件和一个命令文件,并将这两个文件添加到工程,再编译并装载程序:阅读Dsp原理及应用中fft 用dsp实现的有关程序。双击,启动CCS的仿真平台的配着选项。(3)启动ccs2后建立工程文件FFT.pjt(4)建立源文件FFT.c与链接文件FFT.cmd(5)将这两个文件加到FFT.pjt这个工程中。(6)创建ou
26、t文件(7)加载out文件(8)加载数据(9)观察输入输出波形七. 总结本实验通过学习快速傅里叶变换(FFT)的原理,然后在CCS平台下编程对其进行模拟仿真,对快速傅里叶变换(FFT)有个一个较深刻的理解。并且熟悉了DSP,CCS平台,达到了课程教学的目的。但由于初学DSP,许多东西不明白,以后还需对DSP努力学习研究。通过这次DSP课程设计,加深对DFT算法原理和基本性质的理解,熟悉了FFT的算法原理和FFT子程序的算法流程和应用,掌握了DSP中FFT的设计和编程思想,以及用FFT对连续信号和时域信号进行频谱分析的方法,和使用CCS的波形观察器观察波形和频谱情况。这次课程设计,使我增长了知识,同时也增强了我动手解决问题的能力,锻炼我做事细心、用心、耐心的能力。同时也让我意识到平时的课程文化的学习固然非常重要,但是在与实际相联系的过程中还是有许多问题的,所以在以后的学习生活中,我要努力学习,培养自己独立思考的能力,要加强理论文化与实际操作的联系。参考文献:1.DSP原理及应用其 邹彦,唐冬,宁志刚,王毓银 电子工业出版社2.TMS320C5000系列DSP系统设计与开发实例 汪春梅,孙洪波,任治刚 电子工业出版社3.DSP芯片的原理与开发应用(第三版) 张雄伟,陈亮,徐光辉 电子工业出版社4.实时数字信号处理 SEN M.KUO.BOB H.LEE 中国铁道出版社