基于CCS和ICETEK5509实验箱FFT算法的C语言实现与验证学院:姓名:学号:班级:指导老师:完成报告日期:设计目的1.本课程设计与理论课、实验课一起构成《DSP芯片原理与应用》完整课程体系;2.针对理论课、实验课中无时间和不方便提及内容和需强调重点进行补充与完善;3.以原理算法的实现与验证体会 DSP技术的系统性,并加深基本原理的体会。
二、设计任务1.设计一个以ICETEK550为硬件主体,FFT为核心算法的频谱分析系统方案;2.用C语言编写系统软件的核心部分,熟悉CCS调试环境的使用方法,在CCS IDE中仿真实现方案功能;3.在实验箱上由硬件实现频谱分析。
三、设计内容1. 设计方案原理1)FFT工作原理及工作方式工作原理:快速傅里叶变换是离散傅里叶变换的快速算法,它是根据离散傅氏变换的奇、偶、虚、实等特性,对离散傅里叶变换的算法进行改进获得的。
它对傅氏变换的理论并没有新的新的发现,但是对于在计算机系统或者说数字系统中应用离散傅里叶变换,可以说是进了一大步。
设x(n)为N项的复数序列,由DFT变换,任一 X(n)的计算都需要NT次复数乘法和N(N-1)次复数加法,而一次复数乘法等于四次实数乘法和两次实数加法,一次复数加法等于两次实数加法。
所以作一次离散傅里叶变换需要作 4NT次实数乘法及N(4N-2)次实数加法。
而在FFT中,利用 Wn的周期性和对称性,把一个 N项序列分为两个 N/2项的子序列,每个N/2点DFT变换需要(N/2) 2次运算,再用N次运算把两个N/2点的DFT 变换组合成一个N点的DFT而如果我们将这种“一分为二”的思想不断进行下去,直到分成两两一组的 DFT运算单元,那么 N点的DFT就只需要作(N/2)(log2N)次复数乘法和N (log2N)次复数加法。
这样,运算量的节约就很大,这就是 FFT的优越性。
工作方式:第一步,将1个N点的时域信号分成N个1点的时域信号,然后计算这N 个1点时域信号的频域,得到N个频域的点,然后将这个N个频域的点按照一定的顺序加起来,就得到了我们需要的频谱。
这里每个点的意思是复数,都有实部和虚部。
认真看蝶形图可以看出它是按照比特反转顺序来分解的。
第二步,计算每个点的频谱,这一步很简单,因为一个时域的点的频谱的数值就是它自己,所以这一步什么也不需做,但需明白这时候 N 个点不是时域信号了,而是频域信号。
第三步,将这 N 个频域信号结合起来,这一步是最麻烦的一步。
就是和前面时域分解的顺序相反,将2个1 点的频域信号变成 1 个2点的频域信号,再将 2个 2 点的频域信号变成 1 个 4 点的频域信号,一直到结束。
2)DSP工作原理数字信号处理器(DSP)是一种可编程的高性能处理器,近年来发展很快。
它不仅适用于数字信号处理,而且在图像处理、语音处理、通信等领域得到了广泛地应用。
通用的微处理器在运算速度上很难适应信号实时处理的要求。
数字信号处理器中集成有高速的乘法器硬件,能快速地进行大量数据的乘法海和加法运算。
快速傅里叶变换的出现使得 DFT在实际应用中得到了广泛的应用。
3)A/D 模数转换原理TMS320VC5509 模数转换模块带内置采样和保持的 10 位模数转换模块 ADC,最小转换时间为500ns,最大采样率为21.5kHz。
它有2个模拟输入通道( AIN0—AIN1 )。
模数转换模块接到启动转换信号后,开始转换第一个通道的数据。
经过一个采样时间的延迟后,将采样结果放入转换结果寄存器总保存。
转换结束后设置标志,等待下一个启动信号。
模数转换相对于计算机来说是一个较为缓慢的过程。
一般采用中断方式启动转换或保存结果,这样在 CPU 忙于其他工作时可以少占用处理时间。
设计转换程序应首先考虑处理过程如何与模数转换的时间相匹配,根据实际需要选择适当的触发转换的手段,也要能及时地保存结果2.设计方案流程图:1)FFT程序流程框图:2) A/D 转换流程框图开始初始化CPU睛钟" tMIF. AD 釆样时钟启动ADO 道采集(连续236次)ff 入绕冲区“ADC启刚AU1通逋采集{连续2%次)存入缓冲隨nADCI3.主要实现方法1)在CCS 上进行软件仿真:A. 参考教材P371的14.3节完成CCS 环境中的FFT 工程的建立; 本工程的建立有点投机取巧,不太符合老师的要求,只是直接将书上给的 FFTd 故成了头文件FFT.h 然后将其加入之前做实验时时老师给的一个关于 泰勒级数展开的工程c55_si nO 。
B. 设计检测信号,验证FFT 算法的正确性及FFT 的部分性质;基于谱线易于观察分析的角度,故本次软件仿真用的检测信号为正弦函数, 也就是工程中由泰勒级数展开生成的正弦曲线。
下面给出FFT.h 的程序和部分注解:#in elude <math.h>struct compx { float real,imag;}; /* 定义一个复数结构 */struct compx s[257];/*FFT 输入和输出:均从s[1]开始存放*/struct compx EE(struct compx ,struct compx ); /* 定义附复数相乘结构 */void FFT(struct compx *, int ); /*FFT 函数定义 */#define FFT_N 256struct compx EE(struct compx b1,struct compx b2) {struct compx b3;//对两个复数进行乘法运算b3.real=b1.real*b2.real-b2.imag*b2.imag; // 输入参数: 两个以联合体定义的复数b3.imag=b1.real*b2.imag+b1.imag*b2.real; return(b3);}/*输入:xin(实部,虚部),输出:xin(实部,虚部),N:FFT 点数*/ void FFT(struct compx *xin, int N){int f,m,nv2,nm1,i,k,j=1,l; struct compx v,w,t; nv2=N/2; /* 变址运算,即把自然顺序变成倒位序,采用雷德算法 */f=N;for(m=1;(f=f/ 2)!=1;m++){;} nm1=N-1; /* 变址运算 */ for(i=1;i<=nm1;i++){if(i<j)/*如果i<j,即进行变址*/ { t=xin[j];xin[j]=xin[i];xin[i]=t;} k=nv2; /* 求 j 的下一个倒位序 */ while(k<j) /*如果k<j,表示j 的最高位为1*/{j=j-k; /* 把最高位变成 0*/k=k/2; /*k/ 2,比较次高位, 以此类推, 逐个比较, 直到某个位为 0*///i,ip 分别表示参加蝶形运算的两个节点// 蝶形运算xin[ip].real=xin[i].real-t.real;j=j+k;}/*fft*/{ int le,lei,ip; float pi; for(l=1;l<=m;l++){le=pow(2,1); lei=le/2; pi=3014159265; v. real=1.0;v.imag=0.0;w. r eal=cos(pi/lei); w.imag=-sin(pi/lei);/* 把 0 改为 1*///FFT 运算核,使用蝶形运算完成 FFT 运算//w 为系数商,即当前系数与前一个系数的商 for(j=1;j<=lei;j++)// 控制计算不同种蝶形结, 即计算系数不同的蝶形结for(i=j;i<=N;i=i+le) //控制计算同种蝶形结运算,即计算系数相同蝶形结{ip=i+lei;t=EE(xin[ip],v);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); // 改变系数,进行下一个蝶形运算}}}}下面给出 main 函数的程序及部分注解struct compx s[257];float w[257];float a[257];float m[257];main(){int i;double x;float pi=3.1415926;for(i=0;i<256;i++){x=280*pi*i/ 256;// 倍频系数为k=280/2 mysin[i]=fun_sin(x);s[i+1].real=mysin[i];// 结构体s 从 1 开始存放s[i+1].imag=0 ;// 两路信号选择实部信号输入让虚部信号为0 }FFT(s,256);〃将256点正弦曲线进行FFTfor(i=1;i<257;i++){w[i]=s[i].real;a[i]=s[i].imag;// 将虚部值赋给数组 am[i]=sqrt(s[i].real*s[i].real+s[i].imag*s[i].imag);?/ 取模计算功率谱} }程序及频谱的分析倍频数为1的sin函数的波形图及系统自带的FFT对它变换后的图形如下:新建工程中对sin函数进行FFT后的实部、虚部如下:虽然倍频数是1但是结构体s中的值是从s[1]开始存放的所以第一根谱线的位置出现在2处,第二根谱线与第一根谱线关于129对称。
由图中可以看出实部只有3.14而虚部的谱线值为128,显然二者不在一个数量级,这正好验证了 sin(nk) — -2j( △( k-n ) - △ (k+n))这一理论公式。
.改变倍频系数,使其倍频系数分别为 64、128、140,观察分析频谱变化如下图所示:istruct rompx s[257]; float 叽257]; float a[257J; floot(n[257];io0z lJ3B£31C-5iot i; doible z;float p“3・ 1415926;for(i-0;i<256;L**t){x«12B*pi*i/256;■ysiolij^f i_ n(x); s[ulj.rcal-t3y3in|i];s[i*l].iiMg=0 ;MSFFT(Se256);Eor|isl;i<25?;i44.)ajil-sjiJ.iinBg;r[i]»-;qr: (s[i] .rwl<«[i] .r( })K3<a?討・B5鼻36 512 768 10? 12366, T 3®M2«-5) (65, -128)1S«3)5 730 »■g XxU ScUastruct COEDX s[257];float w 257];float a 257];float m 257];lmain()int i; double s;float pi-3.1415926;for(i«D;i<256;i++) {z=25o*pi»i/256:Kiysin i]=fun_sin(x;:s[i+l .real=mysin[i];s i+1]・i mag=0 ;•FFT(sJ56);for(i-l;i<257;i++]E i =s[i].real;a i =s[ij m i=sqrt(s[i].reai*s[L].real+! }hlJ▼J T5CC03进1E67-•1E67-0333・5叫5CC(T333$低“・333$・5[C0[ .................. ........... ......................(「' 42;'「k • •府ni ' 17(1 色0) ll28(~oj Tine bn Aato SciletXTIGt COJtipX s[2&7]; laar lc.mf. A [257];loat u[257];—11[ Ireysi n [1 | - ■: __ 1 n (x a[i + L] .nal-myoLn [■ sli*i ].FFT(S F256);Foti Xl-L :i <Z57;lt+ (w[i ]-e[i ].real; a[i ] =■&f i ] .inug r)若增大倍频数两根谱线均往中间跑也就是都朝着对称轴跑,为128时虚部两根谱线一上一下相互抵消;当继续增大倍频系数使其大于 128,虚部两根谱线交换位置变为左上右下,这意味着发生了频谱混跌效应, 因为此程序设的抽样点数为 257,理论上2fs>=fh ,但是实际要2fs>fh,所以 在倍频系数为128时会出现频谱消失,而在倍频系数为140时会出现频谱交 错。