使用CCS进行DSP编程--fft
- 格式:pdf
- 大小:490.59 KB
- 文档页数:14
使⽤CCS进⾏DSP编程--fft使⽤CCS进⾏DSP编程(⼆)——实现FFTpacificxu现在讨论使⽤TI公司的CCS进⾏DSP编程,⾸先假定读者对CCS的使⽤已经⽐较了解,如果读者还不太了解,请参阅《使⽤CCS进⾏DSP编程(⼀)——CCS编程⼊门》及其他CCS的学习⽂档。
作数字信号处理的同志们总是喜欢⽤FFT来对信号处理系统做检验,下⾯⽤闻亭公司的C6xP板、C6xPa板硬件实现FFT算法,本算法对其他的C6x板同样实⽤(只是硬件资源稍微有差异),并通过闻亭公司的PCI仿真器对⽬标板加载运⾏,运⾏结果在CCS中可视化显⽰。
⾸先启动CCS Setup,对仿真器硬件进⾏设置,本⼈使⽤的是闻亭公司PCI 的仿真器⾃带的驱动wtxds6xxxpci.dvr,设置画⾯如下:下⾯就可以运⾏CCS了,在CCS中,创建⼀个新的Project,我的⼯程⽂件放置在如下的⽬录中,读者可以放在⾃⼰喜欢的⽬录下:双击“+”展开fft.mak,可以看到整个⼯程⽂件是空的,我们需要把*.c、*.cmd、*.lib⽂件添加到⼯程⽂件中,⾸先是*.c⽂件,本例中是test.c⽂件,同样的⽅法可以⽤来添加其他的⽂件。
双击⼯程中的源⽂件,会在右边的窗⼝中看见原码:如果*.c⽂件不存在,可以在CCS集成开发环境中⽣成,本例中test.c的主程序源代码如下:调⽤的⼦程序有三个:从上⾯的源程序可以看到,使⽤CCS 的C 语⾔编程跟普通的C 语⾔编程没有太⼤的区别,这正是TI 所追求的,兼容的ANSI C 标准和如此的编译⾼效率也正是TI 的领先之处。
读者可以不必学习烦琐的汇编和线性汇编,直接对数字信号处理的算法进⾏研究,同时享受⾼速的处理速度,只有在对速度要求极严的条件下,不得不使⽤汇编和线性汇编,那时读者已经有了⼀定的基础,再学习汇编语⾔已是⽔到渠成。
⽽使⽤C 语⾔编程是⼤势所趋。
如果有⼈对算法本⾝感兴趣,请参阅胡⼴书⽼师的《数字信号处理—理论、算法与实现》第5章快速傅⽴叶变换,这⾥不在对算法进⾏展开讨论。
数字信号处理实验实验1 快速傅里叶变换FFT 算法实验一、实验目的:1、加深对离散信号的DFT 的理解和FFT 算法的运用。
2、学会用mtalab 求解信号的频谱图。
3、学会用DSP 硬件进行频谱分析。
二、实验设备计算机,ccs3.3软件,DSP CPU 挂箱,DSP 仿真器,导线三、实验原理N 点序列的DFT 和IDFT 变换定义式如下:10[][]N kn N n X k x n W-==∑, 101[][]N kn N k x n X k W N --==∑ 利用旋转因子2j nk knN N W e π-=具有周期性,可以得到快速算法(FFT )。
在MATLAB 中,可以用函数X=fft (x ,N )和x=ifft (X ,N )计算N 点序列的DFT 正、反变换。
四、实验内容:1、利用MATLAB 编程完成计算,绘出下式时域图形,并用FFT 求取其傅里叶变换画出相应的频谱图,并分析、说明实验结果。
x=0.5*sin(2*pi*15*t)+2*sin(2*pi*40*t);采样频率fs=100Hz ,采样点数为128点。
2、运行ccs 软件,对给定的语音信号进行采集,并应用DSP 挂箱分析该信号的频谱。
相应的实验步骤(1)安装仿真器TDS510驱动(位置在f 盘根目录下).(2)仿真器参数设置打开setup ccstudio 从Familly 中查找C55xx 系列,然后选择C5509 TDS510并将其拖到到左侧窗口。
右键C5509打开属性装载仿真器的配置参数CCstudio_v3.3//cc//bin/TDS510.cgf.(3)打开ccs3.3链接仿真器与电脑点击Debug —connect ;打开已建立的项目点击project—open—fft.pjt;装载编译好的程序fft.out,file--load program—fft.out。
在k++处设置断点,观察采集到的语音信号。
DSP程序:CCS环境下的FFT程序(以8点的为例做了详细解析)2009-11-04 09:35********************************************************************* N(8-1024) points FFT Program *********************************************************************.title "fft.asm".mmregs.copy "coeff.inc".def _c_int00sine: .usect "sine",512cosine: .usect "cosine",512fft_data: .usect "fft_data",2048d_input: .usect "d_input",2048fft_out: .usect "fft_out",1024STACK .usect "STACK",10K_DATA_IDX_1 .set 2K_DATA_IDX_2 .set 4K_DATA_IDX_3 .set 8K_TWID_TBL_SIZE .set 512K_TWID_IDX_3 .set 128K_FLY_COUNT_3 .set 4*** N points FFT ***K_FFT_SIZE .set 16 ;N=8K_LOGN .set 4 ;LOG(N)=LOG(8)=3.bss d_twid_idx,1.bss d_data_idx,1.bss d_grps_cnt,1.sect "fft_prg" ;*** Bit Reversal Routine ***.asg AR2,REORDERED.asg AR3,ORIGINAL_INPUT.asg AR7,DA TA_PROC_BUF.text_c_int00:SSBX FRCTSTM #STACK+10,SPNOP ;put a probe,input 2N data into d_input(dm) ;include Re and ImSTM #sine,AR1 ;move sine1(512) into sine(dm)RPT #511 ;MVPD sine1,*AR1+STM #cosine,AR1 ;move cosine1 into cosine RPT #511 ;MVPD cosine1,*AR1+STM #d_input,ORIGINAL_INPUTSTM #fft_data,DATA_PROC_BUFMVMM DATA_PROC_BUF,REORDERED ;RECORDERED point fft_data too STM #K_FFT_SIZE-1,BRCRPTBD bit_rev_end-1STM #K_FFT_SIZE,AR0 ;this is double words orderMVDD *ORIGINAL_INPUT+,*REORDERED+ ;Bit ReversalMVDD *ORIGINAL_INPUT-,*REORDERED+MAR *ORIGINAL_INPUT+0Bbit_rev_end:* * * * FFT Code * * * * *.asg AR1,GROUP_COUNTER.asg AR2,PX.asg AR3,QX.asg AR4,WR.asg AR5,WI.asg AR6,BUTTERFL Y_COUNTER.asg AR7,STAGE_COUNTER* * * stage 1 * * *STM #0, BK ;why not=16?LD #0, ASM;LD #-1, ASM ;protect flowover ,all output/2STM #fft_data,PXLD *PX,16,A ;AH:=Re[x(0)]STM #fft_data+K_DATA_IDX_1,QX ;QX point Re[x(4)]STM #K_FFT_SIZE/2-1,BRC ;stage 1 is N/2-1RPTBD stage1end-1STM #K_DA TA_IDX_1+1,AR0SUB *QX,16,A,B ;BH=Re[x(0)]-Re[x(4)]ADD *QX,16,A ;AH=Re[x(0)]+ Re[x(4)]STH A,ASM,*PX+ST B,*QX+||LD *PX,ASUB *QX,16,A,B ;BH=Im[x(0)]-Im[x(4)]ADD *QX,16,A ;AH=Im[x(0)]+Im[x(4)]STH A,ASM,*PX+0ST B,*QX+0% ;BK=0 why here circle access ?||LD *PX,Astage1end:* * * Stage 2 * * *STM #fft_data,PXSTM #fft_data+K_DATA_IDX_2,QXSTM #K_FFT_SIZE/4-1,BRCLD *PX,16,A ;AH=Re[x(0)]+ Re[x(4)],AH=1RPTBD stage2end-1STM #K_DA TA_IDX_2+1,AR0;1st butterflySUB *QX,16,A,B ;BH={Re[x(0)]+ Re[x(4)]}-{Re[x(2)]+ Re[x(6)]},BH=0ADD *QX,16,A ;AH={Re[x(0)]+ Re[x(4)]}+{Re[x(2)]+ Re[x(6)]},AH=2STH A,ASM,*PX+ST B,*QX+||LD *PX,ASUB *QX,16,A,B ;BH={Im[x(0)]+ Im[x(4)]}-{Im[x(2)]+ Im[x(6)]},BH=0ADD *QX,16,A ;AH={Im[x(0)]+ Im[x(4)]}+{Im[x(2)]+ Im[x(6)]},BH=0STH A,ASM,*PX+STH B,ASM,*QX+;2nd butterflyMAR *QX+ADD *PX,*QX,A ;AH=+,=1SUB *PX,*QX-,B ;BH=-,=1STH A,ASM,*PX+SUB *PX,*QX,A ;AH=-,=-1,note:subST B,*QX||LD *QX+,B ;very important, " BH= {Re[x(2)]- Re[x(6)]} ",=1******************************************************************************** **********ST A,*PX ; right!!!||ADD *PX+0%,A ; note:this order include BHST A,*QX+0% ;||LD *PX,A***************** my modify***************************************************************; ST A,*PX; ||ADD *PX+0%,B; ST B,*QX+0%; ||LD *PX,A******************************************************************************** *********stage2end:* * * Stage 3 through Stage logN * * *STM #K_TWID_TBL_SIZE,BKST #K_TWID_IDX_3,d_twid_idxSTM #K_TWID_IDX_3,AR0STM #cosine,WRSTM #sine,WISTM #K_LOGN-2-1,STAGE_COUNTERST #K_FFT_SIZE/8-1,d_grps_cntSTM #K_FL Y_COUNT_3-1,BUTTERFL Y_COUNTERST #K_DATA_IDX_3,d_data_idxstage:STM #fft_data,PXLD d_data_idx,A ;A:=8ADD *(PX),A ;A:=2008STLM A,QX ;this time QX piont what?;my thought:point the eighth space(ccs test);may relocate QX pointerMVDK d_grps_cnt,GROUP_COUNTERgroup:MVMD BUTTERFLY_COUNTER,BRCRPTBD butterflyend-1LD *WR,T ;T:=1,cos0MPY *QX+,A ;A=000001FFFCMACR *WI+0%,*QX-,A ;T=0,sin0,WI next piont 0.707,-1 ADD *PX,16,A,B ;B=0000040000,0000010000ST B,*PX ;the first ouput:1/8*||SUB *PX+,B ;B=0000000000,0000010000ST B,*QX ;||MPY *QX+,A ;A=0000000000,000000B504 MASR *QX,*WR+0%,A ;T=0 ,WR next piont 0.707,0;SFTL A,4,AADD *PX,16,A,B ;B=0000000000,OVB=1ST B,*QX+||SUB *PX,B ;B=0000000000 ,00FFFE0000LD *WR,T ;T:=0.707,0ST B,*PX+ ;||MPY *QX+,A********************************************************* butterflyend:; Update pointers for next groupPSHM AR0MVDK d_data_idx,AR0MAR *PX+0MAR *QX+0BANZD group,*GROUP_COUNTER-POPM AR0MAR *QX-;Update counters and indices for next stageLD d_data_idx,A ;A:=8SUB #1,A,B ;B:=7STLM B,BUTTERFL Y_COUNTER ;butterfly_counter:=7 STL A,1,d_data_idx ;d_data_idx:=4LD d_grps_cnt,A ;A:=0(8/8-1)STL A,ASM,d_grps_cnt ;d_grps_cnt=A/2LD d_twid_idx,A ;A:=128STL A,ASM,d_twid_idx ;d_twid_idx=A/2BANZD stage,*STAGE_COUNTER- ;stage_counter:=0 MVDK d_twid_idx,AR0fft_end:* * * Compute the power spectrum * * *STM #fft_data,AR2STM #fft_out,AR4STM #K_FFT_SIZE-1,BRCNOPRPTB power_end-1SQUR *AR2+,ASQURA *AR2+,ASTL A,-1,*AR4+power_end:nophere: B here.end。
使用CCS进行DSP编程(四)——实现Host和DSP通信pacificxu首先对题目进行一下解释,之所以取这个名字,是为了与前面三篇文章相对应,连成一个系列,这里不仅仅涉及使用CCS进行DSP编程,主机端的程序便是用Visual C++实现的。
通信包括许多手段:中断、mailbox、直接数据传输等等,这里并不一一列举。
现在讨论实现Host和DSP通信。
假定读者对CCS的使用已经比较了解,并有了一定的CCS编程经验。
如果读者还不太了解,请参阅《使用CCS进行DSP 编程(一)—— CCS编程入门》、《使用CCS进行DSP编程(二)——实现FFT》、《使用CCS 进行DSP编程(三)——实现DMA和Interrupt》及其他CCS的学习文档。
下面用闻亭公司的C6xP板硬件和闻亭公司的PCI仿真器为例,来实现Host 和DSP 通信。
对于‘ C6Xpa板同样有效。
闻亭公司的C6xP板是一款具有PCI接口的高速信号处理EVM板,接口芯片是AMCC 的S5933,兼容PCI Local Bus Revision 2.1 协议。
PCI 接口比较适合用来进行Host和DSP的高速大数据量数据交换。
主机通过HPI接口可直接访问DSP的所有存储空间,允许主机初始化DSP,可以从主机加载程序。
前面几篇文章所讲的都是从JTAG接口加载程序,这样比较适合于程序的开发调试,对于实际的系统来说,大部分都是系统自己从EEPROM或Flash加载,现在我们可以从主机通过应用程序来加载,基于此,许多耗时的算法PC机不能实时完成的可以由DSP来完成。
这个过程可以这样来描述:PC机执行应用程序,加载算法到DSP端,并将需要处理的数据传送到DSP,DSP计算完成后将数据传回PC,整个过程由PC 来控制启动、工作、完成,使用起来比较方便。
当然,DSP算法还需要首先用仿真器通过JTAG接口调试好才行。
接下来看看实现这个功能的一个典型系统框图:在这个框图里,我简化了主机PC执行程序的其他部分,突出了与DSP进行通信有关的内容。
使用CCS进行DSP编程(三)——实现DMA和Interruptpacificxu现在讨论在CCS进行DSP编程来实现DMA和Interrupt功能。
假定读者对CCS的使用已经比较了解,并有了一定的CCS编程经验。
如果读者还不太了解,请参阅《使用CCS进行DSP编程(一)——CCS编程入门》、《使用CCS进行DSP编程(二)——实现FFT》及其他CCS的学习文档。
下面用闻亭公司的C6xPa板硬件和闻亭公司的PCI仿真器为例,来实现DSP 的DMA传输和硬件Interrupt功能。
首先来描述一下使用的硬件资源。
闻亭公司的C6xPa板有两路独立的最高采样率为40MHz精度为12bit的A/D,它与DSP的EXT_INT7相连,可以产生外部中断信号,通过FPGA的逻辑可以控制A/D的采集和采集多少数据产生一次中断,采集的数据放在DPRAM中(0x1400000开始的地址空间),通过DMA 传输到DSP芯片上的存储器中(0x80000000开始的地址空间)。
在C语言环境中使用DMA和Interrupt功能,需要包含两个头文件<dma.h>和<intr.h>,同时要用到相应的运行时库文件“csl6201.lib”和“dev6x.lib”。
对这两组头文件和运行时库文件,我们深入研究一下,看一看我们比较关心的函数有哪些。
下一次用到这些函数时,别忘了带上相应的运行时库文件%*&^*&^喔。
在dev6x.lib库文件中,直接与实现DMA和Interrupt功能相关的函数有如下几个:dma_initdma_global_initdma_resetintr_resetintr_initintr_hookintr_mapintr_isnintr_get_cpu_intrisr_jump_table在csl6201.lib库文件中,直接与实现DMA功能相关的函数有如下几个: DMA_AllocGlobalRegDMA_GetEventIdDMA_GBL_PRIV ATEDMA_OpenDMA_StartDMA_HCHA0DMA_HCHA1DMA_HCHA2DMA_HCHA3DMA_WaitDMA_SetGlobalRegDMA_ConfigADMA_ConfigBDMA_StopDMA_AutoStartDMA_PauseDMA_ResetDMA_GetGlobalRegDMA_SetAuxCtlDMA_CloseDMA_FreeGlobalRegDMA_InitDMA_GetStatus我们只需其中的一部分便可以实现DMA和Interrupt功能。
使用CCS进行DSP编程(一)——CCS编程入门pacificxuTI公司提供了高效的C编译器和集成开发环境Code Composer Studio,学习‘C6X的编程应该从学习CCS的使用开始。
首先安装CCS,CCS的安装有详细的说明,并配有简短的Quick Time的多媒体介绍,对于没有购买CCS的用户,可以从TI处得到30天的试用版(没有硬件仿真功能)。
使用CCS前需要对CCS进行设置,以Simulator为例,运行Setup CCS C6000 1.20,安装Device Driver,对于有硬件支持的仿真器,可以选择配套的CCS驱动,设置完成的画面如下图所示:用户的界面大致相同。
接下来就可以运行CCS了,CCS提供了比较好的例子,对于初学者,仔细学习这些例子,会起到事半功倍的效果。
在CCS的Help菜单的Tutorial子菜单下,给出了四个教程,分别是:Code Composer Studio Tutorial、Advanced DSP/BIOS Tutorial、Compiler Tutorial和RTDX Tutorial,用户可以从简单的CCS功能开始,如创建一个工程文件Project,到创建一个完善的用户程序一步一步的进行。
下面是Code Composer Studio Tutorial的例子:分别从生成一个简单的“Hello World”程序,到使用DSP/BIOS功能,到程序的调试,实时分析,I/O操作等分6课来讲解,可以领略TI的CCS的强大功能。
下面以“Hello World”程序为例讲一下CCS的使用。
首先打开一个Project文件这些文件的路径如下图所示:打开hello.mak,会看到如下图所示的界面。
将File View栏中的“+”号都打开,会看到整个项目工程中的所有资源。
其中*.c文件和*.h文件与普通的C语言编程中是一致的(TI编译器支持ANSI C标准)。
需要指出的是三个文件:HELLO.CMD、RTS6201.LIB、VECTORS.ASM。
摘要本次课程设计主要运用CCS这一工具实现快速傅里叶变换(FFT)。
CCS(Code Composer Studio)是一种针对TM320系列DSP的集成开发环境,在Windows操作系统下,采用图形接口界面,提供环境配置、源文件编辑、程序调试、跟踪和分析等工具,可以帮助用户在一个软件环境下完成编辑、编译、链接、调试和数据分析等工作。
CCS有两种工作模式,即软件仿真器和硬件在线编程。
软件仿真器工作模式可以脱离DSP芯片,在PC上模拟DSP的指令集和工作机制,主要用于前期算法实现和调试。
硬件在线编程可以实时运行在DSP芯片上,与硬件开发板相结合进行在线编程和调试应用程序。
关键词:CCS; 快速傅里叶变换(FFT);目录第1章概述 (2)1.1设计任务 (2)1.2设计要求 (3)第2章快速傅里叶变换FFT的原理 (3)2.1离散傅里叶变换DFT (3)2.2.快速傅里叶变换FFT (4)第3章方案设计 (7)3.1设计程序流程图 (7)3.2在CCS环境下加载、调试源程序 (8)第4章主要参数 (13)4.1N的参数设置 (13)4.2CMD源文件代码: (13)4.3C文件源码: (14)第五章实验结果及分析 (19)5.1作图得到输入信号的功率图谱 (19)5.2FFT变换结果图 (19)5.3改变信号的频率可以再做次实验 (20)课程设计体会 (21)参考文献 (22)第1章概述1.1设计任务1)用DSP汇编语言及C语言进行编程;2)实现FFT运算、对输入信号进行频谱分析。
1.2设计要求1). 研究FFT原理以及利用DSP实现的方法;2). 编写FFT程序3). 调试程序,观察结果。
第2章快速傅里叶变换FFT的原理快速傅里叶变换(FFT)是一种高效实现离散傅里叶变换(DFT)的快速算法,是数字信号处理中最为重要的工具之一,它在声学,语音,电信和信号处理等领域有着广泛的应用。
2.1 离散傅里叶变换DFT对于长度为N 的有限长序列x(n),它的离散傅里叶变换(DFT )为1,1,0,)()(10-==∑-=N k W n x k X n n nkN (1)式中,Nj N e W /2π-= ,称为旋转因子或蝶形因子。
DSP集成开发环境中的混合编程及FFT算法的实现摘要:实现了一种全集成可变带宽中频宽带低通滤波器,讨论分析了跨导放大器-电容(OTA—C)连续时间型滤波器的结构、设计和具体实现,使用外部可编程电路对所设计滤波器带宽进行控制,并利用ADS软件进行电路设计和仿真验证。
仿真结果表明,该滤波器带宽的可调范围为1~26 MHz,阻带抑制率大于35 dB,带内波纹小于0.5 dB,采用1.8 V电源,TSMC 0.18μm CMOS工艺库仿真,功耗小于21 mW,频响曲线接近理想状态。
关键词:Butte1 引言CCS(Code Composer Studio)是TI公司的DSP集成开发环境。
它提供了环境配置、源文件编辑、程序调试、跟踪和分析等工具,帮助用户在一个软件环境下完成编辑、编译链接、调试和数据分析等工作。
与TI提供的早期软件开发工具相比,利用CCS能够加快软件开发进程,提高工作效率。
CCS一般工作在两种模式下:软件仿真器和与硬件开发板相结合的在线编程。
前者可以脱离DSP芯片,在PC机上模拟DSP指令集与工作机制,主要用于前期算法实现和调试。
后者实时运行在DSP芯片上,可以在线编制和调试应用程序。
2 C语言和汇编语言的混合编程TMS320 C5000系列的软件设计通常有三种方法:(1) 用C语言开发;(2) 用汇编语言开发;(3) C和汇编的混合开发。
其中用C语言开发具有兼容性和可移植的优点,有利于缩短开发周期和减少开发难度,但是在运算量较大的情况下,C代码的效率还是无法和手工编写的汇编代码的效率相比,比如FFT运算,用汇编语言开发的效率高,程序执行速度快,而且可以合理利用芯片的硬件资源,但是开发难度较大,开发周期长,而且可读性和可移植性差。
C和汇编的混合编程则可以充分利用前两者的优点,以达到最佳利用DSP资源的目的。
但是,采用C和汇编语言混合编程必须遵循相关函数调用规则和寄存器调用规则,否则会给程序的开发带来意想不到的问题。
CCS上FFT的C语言实现在C语言中实现FFT(快速傅里叶变换)需要以下步骤:1.导入需要的库函数:```c#include <stdio.h>#include <stdlib.h>#include <math.h>```2.定义复数结构体:```ctypedef structfloat real;float imag;```3.定义FFT函数及其辅助函数:```creturn recursiveFFT(x, N);if(N == 1)X[0]=x[0];return X;}for(int k=0; k<N/2; k++)X_even[k].imag + factor.imag}; X_even[k].imag - factor.imag}; }free(X_even);free(X_odd);return X;for(int m=2; m<=N; m *= 2)for(int k=0; k<N; k += m)for(int j=0; j<m/2; j++)u.imag + t.imag};u.imag - t.imag};w = multiply(w, wm);}}}return X;for(int i=0; i<N; i++)int j = i;int k = 0;for(int b=0; b<log2(N); b++)k<<=1;k,=(j&1);j>>=1;}X[k]=x[i];}return X;```4.用例演示:```cint mainint N = 8; // 采样点数{4,0},{5,0},{6,0},{7,0}};for(int i=0; i<N; i++)printf("X[%d] = %f + %fi\n", i, X[i].real, X[i].imag);}free(X);return 0;```上述代码实现了一个基于C语言的FFT算法,对包含8个采样点的信号进行了快速傅里叶变换。
电子信息专业实验报告课程现代电子学实验实验题目基于DSP的正弦信号FFT变换学生姓名评分学号班级同实验者实验时间周三第一大节地点 JB514 电子信息学院专业实验中心一、实验目的1、熟悉CCS 开发工具;2、掌握DSP5402编程方法;3、掌握FFT 算法二、实验内容(含技术指标)利用 CCS3.0开发工具,实现一个正弦信号的FFT 变换,再变换结束后LED 灯闪烁,周期为500ms.三、实验仪器(仪器名称、型号,元器件名称、清单,软件名称、版本等)PC 机一台 , CCS3.0软件四、实验设计方案原理(设计框图,参数计算,单元电路及器件选取,整体电路图等)DFT 是信号分析与处理中的一种重要变换。
因直接计算DFT 的计算量与变换区间长度N的平方成正比,当N 较大时,计算量太大,所以在快速傅里叶变换(简称FFT)出现以前,直接用DFT 算法进行谱分析和信号的实时处理是不切实际的。
4.2.2 时域抽取法基2FFT 基本原理FFT 算法基本上分为两大类:时域抽取法FFT(Decimation In Time FFT,简称DIT-FFT)和频域抽取法FFT(Decimation In Frequency FFT,简称DIF―FFT)。
下面先介绍DIF―FFT 算法。
按n 的奇偶把x(n)分解为两个N/2点的子序列12()(2),0,1,12()(21),0,1,12Nx r x r r Nx r x r r ==⋅⋅⋅-=+=⋅⋅⋅-其中X 1(k)和X 2(k)分别为x 1(r)和x 2(r)的N/2点DFT ,由于X 1(k)和 X 2(k)均以N/2为周期,且2Nk k NNW W +=-,所以X(k)又可表示为1212()()()0,1,12()()()0,1,122kN kN NX k X k W X k k N NX k X k W X k k =+=⋅⋅⋅-+=-=⋅⋅⋅- 与第一次分解相同,将x1(r)按奇偶分解成两个N/4长的子序列 x 3(l)和x 4(l),则有:13/2413/24()()(),0,1,,/41(/4)()()kN kN X k X k W X k k N X k N X k W X k ⎫=+⎪=⋅⋅⋅-⎬+=-⎪⎭用同样的方法可计算出k ⎫开 始送入x (n )£¬M N £½2 M 倒 序L £½1 , M £Ê£½0 , B £ 1P £½2 M £L J k £½ J , N £1 , 2LpN p N W B k X k X B k X W B k X k X k X )()()()()()(+-⇐+++⇐输 出结 束B 2 L £1五.实验步骤1. 建立工程文件,添加相关命令文件和库文件;2.编写程序产生正弦信号序列,相关代码如下for(i=0;i<N;i++){signal[i].real=sin(2*pi*i/N);signal[i].imag=0;}3按照FFT算法编写FFT函数,函数原型void FFT(COMPLEX *Y); COMPLEX定义为一结构体,表示复数,指针Y指向输入数列;在FFT算法中,最重要的是蝶形运算,相关代码如下所示for ( i =0 ; i < num_stages ; i++ ){index =0;for ( j =0; j < leg_diff ; j++ ){for ( upper_leg = j; upper_leg < N ; upper_leg += (2*leg_diff) ){lower_leg = upper_leg + leg_diff;…………}index+=step;}leg_diff = leg_diff /2;step *=2;}4.编写定时器中断函数,主程序完成FFT变换后令指示灯0.5S周期闪烁。
使用CCS软件开发DSP的流程1. 概述在进行DSP(Digital Signal Processor,数字信号处理器)开发时,使用CCS (Code Composer Studio)软件可以提供一套全面的开发环境和工具集。
本文将介绍使用CCS软件开发DSP的流程和基本步骤。
2. 准备工作在开始使用CCS软件开发DSP之前,需要进行一些准备工作,包括: - 安装CCS软件:前往官网下载最新版本的CCS软件,并按照官方指南进行安装。
- 选择合适的DSP平台:根据项目需求选择合适的DSP芯片,并了解该DSP芯片的技术规格和开发文档。
- 准备开发板:根据选择的DSP芯片,准备相应的开发板,并进行连接和配置。
3. 创建项目在CCS软件中创建一个新的项目是开始开发DSP的第一步。
以下是创建项目的步骤: 1. 打开CCS软件,点击“File”菜单,选择“New”的选项。
2. 在新建项目对话框中,选择“CCS Project”,并点击“Next”按钮。
3. 输入项目名称和存储路径,选择目标DSP芯片型号,并点击“Finish”按钮。
4. 编写代码一旦项目创建完成,可以开始编写DSP代码。
以下是编写代码的步骤: 1. 在CCS软件中打开新建的项目。
2. 在项目资源管理器中,选择“Source Files”文件夹,右键点击并选择“New”的选项。
3. 在新建文件对话框中,输入文件名称和文件类型(.c或.cxx),并点击“Finish”按钮。
4. 在新建的源文件中编写DSP相关的代码,可以使用CCS提供的开发工具和库函数。
5. 编译和调试完成代码编写后,需要对代码进行编译和调试。
以下是编译和调试的步骤: 1.点击CCS软件界面上的“Build”按钮,进行代码的编译和构建。
2. 在构建完成后,选择“Debug”菜单,点击“Start Debug Session”选项,进入调试模式。
3. 在调试模式下,可以设置断点、单步执行、查看变量和寄存器等操作,以调试和验证代码的正确性。
实验报告一、实验目的学习和掌握FFT 的定点DSP 实现原理及C28X 编程的技巧,并通过CCS 的图形显示工具,观察输入/输出信号波形以及它们的频谱变化。
二、实验要求在CCS 环境中用汇编语言,编写实现FFT 的程序及连接器命令文件,编译调试程序,并通过CCS 的图形显示工具观察输入/输出信号波形以及频谱变化。
三、实验原理(1) 位反转在DIF-FFT 蝶形运算结构中,输出X(k)按正常顺序存放在存储单元中,即按X(0)、X(1)、X(2)、…X(6)、X(7)的顺序排列,输入x(n)是按x(0)、x(4)、x(2) …x(3)、x(7)的顺序进行寻址。
反转实现用“*BR0++”寻址方式即可。
(2) 蝶形运算如果蝶形运算的两个输入相距B 个点,应用原位运算,则P N L L L W B J X J X J X )()()(11++⇐-- P N L L L W B J X J X B J X )()()(11+-⇐+--式中,第L 级的旋转因子指数LM J p -•=2,12...2,1,01-=-L J ,L=1,2, …, M=log 2N, B=12-L(3) 基2DIT-FFT 运算流图(3)算法流程图四、实验环境软件环境:CCS3.1硬件环境:无五、实验过程、数据记录、处理及结论1、实验步骤本实验需要使用C28X汇编语言来实现FFT,并通过CCS的图形显示工具观察输入\输出信号波形以频谱的变化。
实验步骤如下:(1) 启动CCS,通过project创建工程文件。
(2) 编写CMD文件和汇编源程序。
(3) 编译、连接、单步执行,检查程序的语法错误,检查程序逻辑错误。
(4) 完成编译、连接。
然后选择File/Load Program命令将OUT文件装入。
点RUN启动程序运行。
(5) 借助view/Graph 设置观察波形,并记录。
2、波形记录输入单频正弦波,起始地址FirstIn 。
波形图一所示,他的频谱如图二所示图一图二输出单频正弦波频谱,起始地址V AR_FIRST,波形如图三所示图三3、实验结论输入单频正弦波结果输出脉冲波形很好的验证了FFT程序的逻辑和代码编程的正确性。
《DSP原理及应用》大作业专业:电子信息工程姓名:学号:快速傅立叶变换(FFT)算法实验一、摘要基于CCS的DSP算法仿真实验设计简要介绍了CCS软件的主要功能, 利用CCS软件, 设计数字信号处理实验课程, 实现了FFT算法实验二、引言在当今的数字化时代背景下, DSP控制器以其可靠性高、扩充能力强、可维护性能好,可满足多种场合的应用需要,得到了国内外电子信息界和控制方案支持企业的青睐,被公认为控制实现技术的发展方向。
DSP已成为通信、计算机、消费类电子产品等领域的基础器件,被誉为信息社会革命的旗手。
三.实验原理1.FFT 的原理和参数生成公式:公式(1)FFT 运算公式FFT 并不是一种新的变换,它是离散傅立叶变换(DFT)的一种快速算法。
由于我们在计算DFT 时一次复数乘法需用四次实数乘法和二次实数加法;一次复数加法则需二次实数加法。
每运算一个X(k)需要4N 次复数乘法及2N+2(N-1)=2(2N-1)次实数加法。
所以整个DFT运算总共需要4N^2 次实数乘法和N*2(2N-1)=2N(2N-1)次实数加法。
如此一来,计算时乘法次数和加法次数都是和N^2 成正比的,当N 很大时,运算量是可观的,因而需要改进对DFT 的算法减少运算速度。
根据傅立叶变换的对称性和周期性,我们可以将DFT 运算中有些项合并。
我们先设序列长度为N=2^L,L 为整数。
将N=2^L 的序列x(n)(n=0,1,……,N-1),按N的奇偶分成两组,也就是说我们将一个N 点的DFT 分解成两个N/2 点的DFT,他们又重新组合成一个如下式所表达的N 点DFT:一般来说,输入被假定为连续的。
当输入为纯粹的实数的时候,我们就可以利用左右对称的特性更好的计算DFT。
我们称这样的RFFT 优化算法是包装算法:首先2N 点实数的连续输入称为“进包”。
其次N 点的FFT 被连续运行。
最后作为结果产生的N 点的合成输出是“打开”成为最初的与DFT 相符合的2N 点输入。
#include<stdio.h>#include<math.h>#include<stdlib.h>#define N 1024double sqrt(double n);/*定义复数类型*/typedef struct {double real;double img;double Amp;double Ang;}complex;float amp[N];float ang[N];float real[N];complex x[N], *W; /*输入序列,变换核*/int size_x = 0; /*输入序列的大小,在本程序中仅限2的次幂*/char unuseful;double PI; /*圆周率*/void fft(); /*快速傅里叶变换*/void initW(); /*初始化变换核*/void change(); /*变址*/void add(complex, complex, complex *); /*复数加法*/void mul(complex, complex, complex *); /*复数乘法*/void sub(complex, complex, complex *); /*复数减法*/void output();/*输出快速傅里叶变换的结果*/int main(){int i=0; /*输出结果*/int tmp;PI = atan(1) * 4;printf("输出DIT方法实现的FFT结果\n");/*printf("Please input the size of x:\n");//输入序列的大小scanf("%d", &size_x);printf("Please input the data in x[N]:\n");//输入序列的实部和虚部for (i = 0;i<size_x;i++){printf("请输入第%d个序列:", i);*/FILE *fp;if ((fp = fopen("C:\\trsData_real.txt", "r")) == NULL){printf("Cannot open file, press any key to exit!\n");exit(1);}while (!feof(fp))fscanf(fp,"%d,",&tmp);x[i].real = tmp;real[i] = (float)x[i].real;i++;if (i>1024) break;}fclose(fp);//for (i = 0;i < 1024;i++) {//printf("x[%d].real=%d ", i, (int)x[i].real);//printf("\n");//}FILE *fo;if ((fo = fopen("C:\\trsData_imag.txt", "r")) == NULL){printf("Cannot open file, press any key to exit!\n");exit(1);}i = 0;while (!feof(fo)){fscanf(fo,"%d,",&tmp);x[i].img = tmp;i++;if (i>1024) break;}fclose(fo);//for (i= 0;i < 1024;i++) {//printf("x[%d].img=%d ", i, (int)x[i].img);//printf("\n");//}for (i = 0;i < 1024;i++) {//real_temp = x[i].real;printf("%lf + %lf\n"real,x[i].img);//printf("%d %d +%d %d\n",x[i].real, x[i].img,&x[i].real,&x[i].img);//printf("%d + %d\n", *(int *)ptest++, *(int *)ptest++);//printf("%f,%f\n", x[i].real,x[i].img);//printf(buff);//printf("x[%d].real+x[%d].img=%d+%d", i, i, x[i].img, x[i].real);//printf("%d", x[i].img);//printf("\n");}printf("输出倒序后的序列\n");initW();//调用变换核fft();//调用快速傅里叶变换printf("输出FFT后的结果\n");output();//调用输出傅里叶变换结果函数for (i = 0;i < 1024;i++)x[i].Amp =sqrt( pow(x[i].real, 2) + pow(x[i].img, 2));x[i].Ang = atan(x[i].img / x[i].real);amp[i] = (float)x[i].Amp;ang[i] = (float)x[i].Ang;//printf("%lf %lf", j[i],m[i]);//printf("\n");}return 0;}/*快速傅里叶变换*/void fft(){int i = 0, j = 0, k = 0, l = 0;complex up, down, product;change(); //调用变址函数for (i = 0;i< log(1024) / log(2);i++) /*一级蝶形运算 stage */{l = 1 << i;for (j = 0;j<1024;j += 2 * l) /*一组蝶形运算 group,每个group的蝶形因子乘数不同*/{for (k = 0;k<l;k++) /*一个蝶形运算每个group内的蝶形运算*/{mul(x[j + k + l], W[1024*k / 2 / l], &product);add(x[j + k], product, &up);sub(x[j + k], product, &down);x[j + k] = up;x[j + k + l] = down;}}}}/*初始化变换核,定义一个变换核,相当于旋转因子WAP*/void initW(){int i;W = (complex *)malloc(sizeof(complex) * 1024); //生成变换核for (i = 0;i<1024;i++){W[i].real = cos(2 * PI / 1024*i); //用欧拉公式计算旋转因子W[i].img = -1 * sin(2 * PI / 1024*i);}}/*变址计算,将x(n)码位倒置*/void change(){complex temp;unsigned short i = 0, j = 0, k = 0;double t;for (i = 0;i<1024;i++){k = i;j = 0;t = (log(1024) / log(2));while ((t--)>0) //利用按位与以及循环实现码位颠倒{j = j << 1;j |= (k & 1);k = k >> 1;}if (j>i) //将x(n)的码位互换{temp = x[i];x[i] = x[j];x[j] = temp;}}output();}/*输出傅里叶变换的结果*/void output(){int i;printf("The result are as follows:\n");for (i = 0;i<1024;i++){printf("%.4f+%.4fj\n", x[i].real, x[i].img);}}void add(complex a, complex b, complex *c) //复数加法的定义{c->real = a.real + b.real;c->img = a.img + b.img;}void mul(complex a, complex b, complex *c) //复数乘法的定义{c->real = a.real*b.real - a.img*b.img;c->img = a.real*b.img + a.img*b.real;}void sub(complex a, complex b, complex *c) //复数减法的定义{c->real = a.real - b.real;c->img = a.img - b.img;}。
基于DSP的FFT算法在CCS仿真环境下的实现程序C程序#include "math.h"#define sample_1 256#define signal_1_f 60#define signal_2_f 200#define signal_sample_f 512#define pi 3.1415926int input[sample_1];float fwaver[sample_1],fwavei[sample_1],w[sample_1];float sin_tab[sample_1];float cos_tab[sample_1];void init_fft_tab();void input_data();void fft(float datar[sample_1],float datai[sample_1]);void main(){int i;init_fft_tab();input_data();for (i=0;i<sample_1;i++){fwaver[i]=input[i];fwavei[i]=0.0f;w[i]=0.0f;}fft(fwaver,fwavei);while(1);}void init_fft_tab(){float wt1;float wt2;int i;for (i=0;i<sample_1;i++){wt1=2*pi*i*signal_1_f;wt1=wt1/signal_sample_f;wt2=2*pi*i*signal_2_f;wt2=wt2/signal_sample_f;input[i]=(cos(wt1)+cos(wt2))/2*32768;}}void input_data(){int i;for(i=0;i<sample_1;i++){sin_tab[i]=sin(2*pi*i/sample_1);cos_tab[i]=cos(2*pi*i/sample_1);}}void fft(float datar[sample_1],float datai[sample_1]){int x0,x1,x2,x3,x4,x5,x6,x7,xx;int i,j,k,b,p,L;float TR,TI,temp;for(i=0;i<sample_1;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;x7=(i/128)&0x01;xx=x0*128+x1*64+x2*32+x3*16+x4*8+x5*4+x6*2+x7;datai[xx]=datar[i];}for(i=0;i<sample_1;i++){datar[i]=datai[i];datai[i]=0;}for(L=1;L<=8;L++){b=1;i=L-1;while(i>0){b=b*2;i--;}for(j=0;j<=b-1;j++){p=1;i=8-L;while(i>0){p=p*2;i--;}p=p*j;for(k=j;k<256;k=k+2*b){TR=datar[k];TI=datai[k];temp=datar[k+b];datar[k]=datar[k]+datar[k+b]*cos_tab[p]+datai[k+b]*sin_tab[p];datai[k]=datai[k]-datar[k+b]*sin_tab[p]+datai[k+b]*cos_tab[p];datar[k+b]=TR-datar[k+b]*cos_tab[p]-datai[k+b]*sin_tab[p];datai[k+b]=TI+temp*sin_tab[p]-datai[k+b]*cos_tab[p];}}}for(i=0;i<sample_1/2;i++){w[i]=sqrt(datar[i]*datar[i]+datai[i]*datai[i]);}}处理器选择55系列cmd程序-f 0-w-stack 500-sysstack 500-l rts55.libMEMORY{DARAM: o=0x100, l=0x7f00VECT:o=0x8000, l=0x100DARAM2:o=0x8100,l=0x7f00SARAM: o=0x10000,l=0x30000SDRAM:o=0x40000,l=0x3e0000}SECTIONS{.text: {}>DARAM.vectors: {}>VECT.trcinit:{}>DARAM.gblinit:{}>DARAM.frt:{}>DARAM.cinit:{}>DARAM.pinit:{}>DARAM.sysinit:{}>DARAM2.far:{}>DARAM2.const:{}>DARAM2.switch:{}>DARAM2.sysmem:{}>DARAM2 .cio:{}>DARAM2.MEM$obj:{}>DARAM2 .sysheap:{}>DARAM2 .sysstack:{}>DARAM2 .stack:{}>DARAM2.input:{}>DARAM2.fftcode:{}>DARAM2}。
一实验名称基于CCS和ICETEK5509实验箱FFT算法的C语言实现与验证二实验目的1、熟悉A/D转换的基本原理,FFT的基本原理2、针对理论课、实验课中无时间和不方便提及内容和需强调重点进行补充与完善;3、以原理算法的实现与验证体会DSP技术的系统性,并加深基本原理的体会。
三实验要求1、设计一个以ICETEK5509为硬件主体,FFT为核心算法的频谱分析系统方案;2、用C语言编写系统软件的核心部分,熟悉CCS调试环境的使用方法,在CCS IDE中仿真实现方案功能;3、在实验箱上由硬件实现频谱分析。
四实验原理1、DSP应用系统构成:注:一般的输入信号首先进行带限滤波和抽样,然后进行模数(A/D)转换,将信号变成数字比特流。
根据奈奎斯特抽样定理,对低通信号模拟,为保持信号的不丢失,抽样频率必须至少是输入带限信号的最高频率的2倍,工程上为带限信号最高频率的3-5倍。
2、A/D转换原理A/D转换器是用来通过一定的电路将模拟量转变为数字量。
模拟量可以是电压、电流等电信号,也可以是压力、温度、湿度、位移、声音等非电信号。
但在A/D转换前,输入到A/D转换器的输入信号必须经各种传感器把各种物理量转换成电压信号。
A/D转换后,输出的数字信号可以有8位、10位、12位和16位等。
3.快速傅立叶变换原理频谱分析系统A/D系统设臵FFT系统(DIT)对于有限长离散数字{x[n]},0≤n≤N-1,其离散谱{x[k]}可以由离散傅氏变换(DFT)求得。
不难看出,是周期性的,且周期为N,即,m,l=0,±1,±2….FFT算法可以分为按时间抽取FFT和按频率抽取FFT两大类输入也有和复数之分,一般情况下,都假定输入序列为复数。
FFT算法利用旋转因子的对称性和周期性,加快运算速度。
用定点DSP芯片实现FFT程序时,一个比较重要的问题就是防止中间结果的溢出,防止中间结果的溢出的方法就是对中间数值归一化,而不可能溢出的则不进行归一化。
使用CCS进行DSP编程(二)
——实现FFT
pacificxu
现在讨论使用TI公司的CCS进行DSP编程,首先假定读者对CCS的使用已经比较了解,如果读者还不太了解,请参阅《使用CCS进行DSP编程(一)——CCS编程入门》及其他CCS的学习文档。
作数字信号处理的同志们总是喜欢用FFT来对信号处理系统做检验,下面用闻亭公司的C6xP板、C6xPa板硬件实现FFT算法,本算法对其他的C6x板同样实用(只是硬件资源稍微有差异),并通过闻亭公司的PCI仿真器对目标板加载运行,运行结果在CCS中可视化显示。
首先启动CCS Setup,对仿真器硬件进行设置,本人使用的是闻亭公司PCI 的仿真器自带的驱动wtxds6xxxpci.dvr,设置画面如下:
下面就可以运行CCS了,在CCS中,创建一个新的Project,
我的工程文件放置在如下的目录中,读者可以放在自己喜欢的目录下:
双击“+”展开fft.mak,可以看到整个工程文件是空的,
我们需要把*.c、*.cmd、*.lib文件添加到工程文件中,
首先是*.c文件,本例中是test.c文件,
同样的方法可以用来添加其他的文件。
双击工程中的源文件,会在右边的窗口中看见原码:
如果*.c文件不存在,可以在CCS集成开发环境中生成,
本例中test.c的主程序源代码如下:
调用的子程序有三个:
从上面的源程序可以看到,使用CCS的C语言编程跟普通的C语言编程没有太大的区别,这正是TI所追求的,兼容的ANSI C标准和如此的编译高效率也正是TI的领先之处。
读者可以不必学习烦琐的汇编和线性汇编,直接对数字信号处理的算法进行研究,同时享受高速的处理速度,只有在对速度要求极严的条件下,不得不使用汇编和线性汇编,那时读者已经有了一定的基础,再学习汇编语言已是水到渠成。
而使用C语言编程是大势所趋。
如果有人对算法本身感兴趣,请参阅胡广书老师的《数字信号处理—理论、算法与实现》第5章快速傅立叶变换,这里不在对算法进行展开讨论。
程序的结构本身很简单,使用过C语言的朋友一看就明白,不需要再做进一步的说明,需要指出几点,
1. 本程序中的math.h与Visual C++中的math.h是不同的,TI的CCS专门
为数学计算作了运行时库,是利用硬件对计算作加速的,与Visual C++
中的速度是不可同日而语的。
因此如果我们需要用到相应的“头文件”,
就应该在TI的目录中查找,同时要包含相应的运行时库(*.lib)文件,
我一直在强调这一点,初学者往往忽略这一点而出现许多编译链接错误。
下面的演示中还会看到这一点。
2. 本例是以定点DSP芯片‘C6201为例的。
如果对定点运算还不太熟悉,
只好找些文档来学习一下了,这里也不再展开。
在浮点DSP芯片‘C6701
中本程序可以不加修改地运行,但浮点DSP芯片中可以直接进行有硬件
支持的浮点运算,速度会更快。
3. CCS的C语言中的数据类型是与硬件相关的,使用时需要注意。
char 8 bits
bits
short 16
int 32 bits
bits
long 40
bits
float 32
double 64 bits
TMS320C6000 Online Programmer's Guide (SPRH048) Copyright?2000 Texas Instruments
接下来继续进行,向工程中添加*.cmd文件。
读者现在应该会执行这个操作了,如果没有就自己造一个吧,也可以拿别人的来改造一下。
其中有些不太明白也没有关系,但是在与具体的硬件相关的地方还是要搞明白。
首先要搞明白目标板“target”上到底有多少存储空间,包括DSP芯片内部有多大空间,目标板上有多少外部存储器(SDRAM、SBSRAM、双口RAM),以及它们的其始地址和长度,以我使用的闻亭公司‘C6Xpa板为例,
存储器类型起始地址存储器大小结束地址SDRAM 0x2000000 4M*32bit (0x400000*4) 0x3000000 SBSRAM 0x400000 128k*32bit (0x20000*4) 0x480000
0x1404000 DPRAM 0x1400000 4k*32bit (0x1000*4)
在这里还要强调一点,是“*32bit”,因此SDRAM的结束地址是0x2000000 + 0x400000*4 = 0x3000000
而不是
0x2000000 + 0x400000 = 0x2400000
其他存储空间也是如此。
许多同志们忽略了这一点,在使用数组、指针及对空间地址操作时造成“不可理解”的错误,“我往仫个地址写数怎么找不到,#%^#&^%%^———坏了!”,好好研究一下,就不好意思这么快下结论了。
下面是我用的*.cmd文件的源代码,需要的话可以拿去用喔。
里面“.vec、.text ….”的东西可以先不考虑,留给CCS去处理好了。
只要保证定义的空间在物理上存在就可以了。
心急的朋友会开始编译了,
又会出现下面的结果,
“$%*^&^,又忘了加运行时库!”。
(下次再忘就不应该了!)。
这里展开一点,有些朋友说:“我包含了头文件<intr.h>,调用中断函数intr_hook()时怎么也编译链接通不过,去掉这一句就通过了。
”大家现在就应该知
道怎么处理这个问题了吧?熟悉C语言编程的同志都知道“*.lib”的实质,中断函数intr_hook()在“dev6x.lib”里。
加上这个库问题估计该解决了吧! TI的运行时库都有具体的说明,如果大家实在懒得去看,又不想知其所以然,有一个绝招在此:“Find all *.lib in TI目录”一个一个试一下好了。
我们的问题解决了,接下来看一看能不能运行,执行对不对。
装入“fft.out”文件,
然后运行程序(F5)(热键、工具条、菜单都可以用啦),看一下结果对不对,顺便体验一下CCS提供的“Very Good”功能:
弹出对话框,设置一下吧,
会出现下面的画面,
修改一下属性,
下面好看多了,
里面的三个谱峰看起来跟信号里造的三个频率的信号好象是对应的吧。
在源文件
里进行些修改,例如将信号频率改为两个,
重新编译、链接、执行、显示,中间的谱线不见了。
好象我们成功了!(哗哗哗哗哗┉┉)
总结:在这里演示了使用CCS的C语言实现FFT程序,仅仅是实现而已。
一个实际的系统,需要做许多优化处理,对核心算法进行详细的分析、规划,初学时可以先不考虑这些,等熟悉后在进行深入研究。