中南大学DSP实验报告文档格式.docx
《中南大学DSP实验报告文档格式.docx》由会员分享,可在线阅读,更多相关《中南大学DSP实验报告文档格式.docx(32页珍藏版)》请在冰豆网上搜索。
![中南大学DSP实验报告文档格式.docx](https://file1.bdocx.com/fileroot1/2022-11/28/496f4631-3b4f-486b-bf77-b195718ea01d/496f4631-3b4f-486b-bf77-b195718ea01d1.gif)
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点输入。
使用这战略,我们可以划分FFT的大小,它有一半花费在包装输入O(N)的操作和打开输出上。
这样的RFFT算法和一般的FFT算法同样迅速,计算速度几乎都达到了两次DFT的连续输入。
下列一部分将描述更多的在TMS320C54x上算法和运行的细节。
2.抽样定理
在应用DSP进行信号处理过程中,经常需要对信号进行采集,而采集工作一般通过AD转换器件完成,AD器件在工作时不可能取得连续的值,只能间隔一段时间进行一次转换,得到转换结果后再进行下一次转换。
这样,对连续变换的信号只能在离散时间点上进行取样,这也叫抽样过程。
抽样是在离散时间间隔对连续时间信号(例如模拟信号)的采集,它是实时信号处理中的基本概念。
模拟信号由一些离散时间的值来代表,这些抽样的值等于原始的模拟信号在离散时间点的取值。
DSP器件只能通过抽样的方法得到离散的信号,我们如何对信号进行采样才能获得原有信号所具备所有频率特征,这是采样定理所涉及的问题。
采样定理规定对模拟信号应该以多大的速率抽样,以保证能够捕捉到包含在信号中的相关信息或者经过抽样后能够保留相关的信息。
抽样定理:
如果信号的最高频率分量是
,为了使抽样值能够完整地描述信号,那么至少应该以
的速率进行抽样。
即
≥
,其中
是抽样频率或抽样率。
因此,如果模拟信号中的最大频率分量为4kHz,那么,为了保留或捕捉信号中的所有信息,应该以8kHz或者更高的抽样率进行抽样。
小于抽样定理规定的抽样率进行抽样将导致频谱折叠,或者相频混叠进入到希望的频带内,以至于我们在把抽样的数据转回到模拟信号时不能恢复出原始信号。
信号有很多能量常常在感兴趣的最高频率之外或者包含噪声,信号的能量在很宽的频率范围内是不变的。
例如,在电话中感兴趣的最高频率是大约3.4kHz,而语音信号可能超过10kHz。
因此,如果我们没有将感兴趣的带宽之外的信号和噪声移去,那么将违反抽样定理。
在实际应用中,让信号通过一个模拟抗混叠滤波器,可以达到移去感兴趣频带之外信号的目的。
3.快速傅立叶变换应用
通过FFT计算,我们能直观地分析信号的频率特征,了解信号中的主要频率分量的频点。
4.程序流程图:
四.实验步骤
1.实验准备
-设置软件仿真模式
CCS可以工作在纯软件仿真环境中,就是由软件在PC机内存中构造一个虚拟的DSP环境,可以调试、运行程序。
但一般软件无法构造DSP中的外设,所以软件仿真通常用于调试纯软件的算法和进行效率分析等。
在使用软件仿真方式工作时,无需连接板卡和仿真器等硬件。
(1)单击桌面上图标:
进入CCS设置窗口。
(2)在出现的窗口中按标号顺序进行如下设置:
图3.1.1删除掉原有的驱动设置
(3)在出现的窗口中按标号顺序进行如下设置:
图3.1.2选择软件仿真F2812芯片驱动
此时CCS已经被设置成Simulator方式(软件仿真TMS320F2812器件的方式),如果一直使用这一方式就不需要重新进行以上设置操作了。
2.设置CCS通过ICETEK-5100USB仿真器连接ICETEK–F2812-A硬件环境进行软件调试和开发。
(1)单击桌面上图标:
(2)在出现的窗口中按标号顺序进行如下设置:
图3.1.3删除掉原有的驱动设置
(3)在出现的窗口中按标号顺序进行如下设置:
图3.1.4选择硬件仿真F2812芯片驱动
(4)接着在下面的窗口中按标号顺序进行如下选择:
图3.1.5设置gel文件
(5)在出现的窗口按标号顺序进行如下设置:
图3.1.6加入gel文件
(6)在出现的窗口按标号顺序进行如下设置:
图3.1.7退出ccs设置界面
(7)在出现的窗口中按标号顺序进行如下设置:
图3.1.8保存退出
以上设置完成后,CCS已经被设置成Emulator的方式(用仿真器连接硬件板卡的方式),并且指定通过ICETEK-5100USB仿真器连接ICETEK–F2812-A评估板。
如果您需要一直使用这一方式就不需要重新进行以上设置操作了。
2.
启动CCS
1.启动Simulator软件仿真方式(请确认已按照上面说明设置为软仿真
方式了。
)设置好软仿真驱动后,双击桌面上图标:
2.启动Emulator方式
(1)首先将实验箱电源关闭。
连接实验箱的外接电源线。
(2)检查ICETEK-5100USB仿真器的黑色JTAG插头是否正确连接到ICETEK–F2812-A评估板的P5插头上。
注:
仿真器的插头中有一个孔加入了封针,与P5插头上的缺针位置应重合,保证不会插错。
(3)检查其他连线是否符合实验要求。
检查实验箱上三个钮子开关位置是否符合实验要求。
(4)打开实验箱上电源开关(位于实验箱底板左上角),注意开关边上红色指示灯点亮。
ICETEK–F2812-A评估板上指示灯VCC点亮。
如果打开了ICETEK-CTR的电源开关,ICETEK-CTR板上指示灯POWER点亮。
如果打开了信号源电源开关,相应开关边的指示灯点亮。
(5)用实验箱附带的USB信号线连接ICETEK-5100USB仿真器和PC机后面的USB插座,注意ICETEK-5100USB仿真器上指示灯Power和Run灯点亮。
(6)双击桌面上仿真器初始化图标:
如果出现下面提示窗口,表示初始化成功,按一下空格键进入下一步操作。
图3.1.9仿真器复位
如果窗口中没有出现“按任意键继续…”,请关闭窗口,关闭实验箱电源,再将USB电缆从仿真器上拔出,返回第
(2)步重试。
如果窗口中出现“Theadapterreturnedanerror.”,并提示“按任意键继续…”,表示初始化失败,请关闭窗口重试两三次,如果仍然不能初始化则关闭实验箱电源,再将USB电缆从仿真器上拔出,返回第
(2)步重试。
(7) 双击桌面上图标:
启动CCS3.3。
(8) 如果进入CCS提示错误,先选“Abort”,然后用“emurst”初始化仿真器,如提示出错,可多做几次。
如仍然出错,拔掉仿真器上USB接头(白色方形),按一下ICETEK–F2812-A评估板上S1复位按钮,连接USB接头,再做“快捷方式xdsrstusb”。
(9) 如果遇到反复不能连接或复位仿真器、进入CCS报错,请打开Windows的“任务管理”,在“进程”卡片上的“映像名称”栏中查找是否有“cc_app.exe”,将它结束再试。
(10)与ccs的以前版本(例如ccs2.21版本)不同的是,仅仅进入ccs3.3软件环境后,CCS软件和2812芯片还无法连接在一起,如下图显示:
图3.1.10未连接到2812芯片显示
(11)此时要按照如下图所示操作,才能把ccs软件和2812芯片连接在一起,然后才能对2812芯片进行控制。
图3.1.11设置连接2812芯片
(12)如下图所示,我们就可以确认CCS软件和2812芯片连接在一起了。
图3.1.12成功连接上2812板卡
(13)
2.打开工程,浏览程序,工程目录为C:
\ICETEK\F2812\DSP281x_examples\lab0503-FFT
3.编译并下载程序
4.打开观察窗口:
选择菜单View->
Graph->
Time/Frequency…进行如下图所示设置。
图3.2.5.7观察窗口设置1
图3.2.5.8观察窗口设置2
图3.2.5.9观察窗口设置3
5.清除显示:
在以上打开的窗口中单击鼠标右键,选择弹出式菜单中“ClearDisplay”功能。
6.设置断点:
在程序FFT.c中有注释“breakpoint”的语句上设置软件断点。
7.运行并观察结果
⑴选择“Debug”菜单的“Animate”项,或按F12键运行程序。
⑵观察“FFT”窗口中时域和频域图形。
图3.2.5.10结果显示
通过观察频域和时域图,程序计算出了测试波形的功率谱,与CCS计算的FFT结果相近。
8.退出CCS
9.实验准备
(1)连接实验设备:
请参看本书第三部分、第一章、二。
(2)准备信号源进行AD输入。
注意:
如果使用2812单板,请把您的信号源输入端接到P2扩展接口上的ad输入引脚,把地线接到扩展接口上的AGND引脚上。
(具体位置参考ICETEK–F2812-A评估板原理图)
①取出1根实验箱附带的信号线(如右图,两端均为单声道语音插头)。
②用1根信号线连接实验箱左侧信号源的波形输出A端口和“A/D输入”模块的“ADCIN2”插座注意插头要插牢、到底。
这样,信号源波形输出A的输出波形即可送到ICETEK–F2812-A板的AD输入通道0。
③-向内侧按波形频率选择旋钮,直到标有正弦波的指示灯点亮。
-上下调节波形频率选择旋钮,直到标有1K-10KHz的指示灯点亮。
-调节幅值调整旋钮,将波形输出A的幅值调到最大。
10.设置CodeComposerStudio3.3在硬件仿真(Emulator)方式下运行
请参看本书第三部分、第一章、四、2。
11.启动CodeComposerStudio3.3
请参看本书第三部分、第一章、五、2。
选择菜单Debug→ResetCPU。
12.打开工程文件
工程目录为:
C:
\ICETEK\F2812\DSP281x_examples\Lab0506-Nyquist
13.编译、下载程序,选择菜单Debug->
GoMain,使程序运行到main函数入口位置。
14.设置软件断点和观察窗口
-打开源程序adc.c,在有注释“breakpoint”的行上加软件断点。
-选择菜单View->
Time/Frequency…进行如下设置:
图3.2.5.20观察窗口设置1
15.运行程序,测算AD采样频率
按“F5”键运行,用示波器测试采样频率:
示波器探头地线可以连接到“测试点”模块
的“AGND”上,用示波器探头测量“测试点”模块的“DAOUT1”上。
调节示波器旋钮,测出方波的频率,这一频率是AD采样频率的1/2,现假设测得的频率
为10.75KHz,那么AD的采样频率为21.5KHz。
选择菜单Debug->
Halt,停止程序运行。
将示波器探头改到测试信号源I的输出,可以连接到“测试点”模块的“ADCIN0”上。
16.打开观察窗口观察波形的频域统计结果
图3.2.5.21观察窗口设置2
-注意在打开窗口中的横轴单位实际上应该是kHz。
17.运行程序观察显示
-按“F12”运行程序,过一会然后停止运行程序,观察两个窗口中的显示。
-观察示波器的频率统计,对照“FFT”窗口的尖峰指示(可以用鼠标将光标移动到尖峰位置,再从状态条读出频率值,如图),看是否相近。
图3.2.5.22查看结果
-顺时针微调信号源I的“频率微调”旋钮,使频率增大,观察到“FFT”尖峰向频率高端(右侧)移动。
对照频率测量值和FFT计算值。
18.观察混叠现象
-将信号源I“频率微调”旋钮逆时针调到头;
“频率选择”旋钮切换到“10kHz-20kHz”档。
-顺时针微调信号源I的“频率微调”旋钮,使频率增大,对照频率测量值和FFT计算值。
五.实验结果
在实验步骤10以前,“FFT”窗口峰值频率随频率值的微调增大,但到了步骤11中,到达某个频率后,“FFT”窗口峰值频率不随频率值的微调增大,反而有减小(向左移动)的现象,这就是信号频率超越了奈奎斯特(Nyquist)频率(也就是采样频率的1/2)后发生的频率混叠现象。
这时“FFT”窗口的频率计算值已经无法正确得到实际信号的频率值。
在固定的采样频率21.5kHz所能测量的信号最高频率不能高于10.75kHz。
换句话说,要测量高频率在10.75kHz的信号,必须保证采样频率大于Nyquist频率=2*10.75kHz才能得到不失真的结果。
7.源程序代码
#include"
DSP281x_Device.h"
//DSP281xHeaderfileIncludeFile
DSP281x_Examples.h"
//DSP281xExamplesIncludeFile
f2812a.h"
#include"
math.h"
#defineNN100
//预处理程序
voidInitForFFT();
voidMakeWave();
voidpp_sgnl()
{
inti,j;
doubletemp_sum;
floattemp_aver;
//去平均值开始
temp_sum=0;
for(i=0;
i<
NN;
i++)
{
temp_sum+=x[1][i];
}
temp_aver=temp_sum/NN;
x[1][i]-=temp_aver;
//去平均值结束
}
//FFT程序
voidfft()
inti,j,k,LE,LE1,L0,L1,tempint;
floatNf,w0,w1,a0,a1,max,tempfloat;
floatb00,b01,b10,b11;
floattempfre;
intshift;
j=0;
max=0;
Nf=0;
//码位倒置
j=code_vector[i];
//code_vector[i]是已倒序好的数组
x[0][i]=x[1][j];
x[1][i]=0;
shift=NN;
//FFT计算
LE=1;
for(i=1;
=M;
i++)//级层循环
LE=2*LE;
//LE为分组间隔
LE1=LE/2;
//LE1为对偶节点的跨距
shift=shift/2;
//为计算旋转银子做准备的,w=cos[系数]+sin[系数]
//[系数]=1/(2的m次方),m为级数,从这一级跳到下一级时,[w]=[w]*[1/2]
for(j=0;
j<
LE1;
j++)
//在同一级中的运算,使用不同的旋转因子,所以其间隔为蝶形数的一半
L0=j;
tempint=j*shift*table_factor;
//对旋转因子w操作,相当于[w]=[w]*[1/2]第一级旋转因子为1,故直接与0想成
w0=Table_cos[tempint];
w1=Table_sin[tempint];
//将旋转因子w转化为正弦余弦,[w]=[cos]+[sin]
while(L0<
NN)
//同一级中,使用相同的旋转因子进行计算,即实虚部分分别想成,然后相加
{
L1=L0+LE1;
//L0与L1相差半个蝶形跨度,L0、L1存放的是一对对偶节点
b00=x[0][L0];
b01=x[0][L1];
b10=x[1][L0];
b11=x[1][L1];
a0=w0*b01-w1*b11;
//w0存放的是sin值,w1存放的是cos值
//b01存放的是L1[实部],b11存放的是L1[虚部]
//这句是计算L1*w[实部],a0=L1*w[实部]=L1[实部]*cos-L1[虚部]sin
a1=w0*b11+w1*b01;
//b01和b11存放的是L1[实部]和L1[虚部]
//这句是计算L1*w[实部],a1=L1*w[虚部]=L1[虚部]*cos+L1[虚部]sin
b01=(b00-a0);
b11=(b10-a1);
b00=(b00+a0);
b10=(b10+a1);
x[0][L0]=b00;
x[0][L1]=b01;
//将计算结果装入原来的寄存器
x[1][L0]=b10;
x[1][L1]=b11;
L0+=LE;
//跨组计算,这是为了计算同一级中不同组里含有相同旋转因子w数值蝶形因子
}
//开始功率谱计算
NN/2;
x[0][i]=sqrt(x[0][i]*x[0][i]+x[1][i]*x[1][i])/NN;
k=0;
for(i=point_of_minfre;
tempfloat=x[0][i];
if(tempfloa>
max)
max=tempfloat;
k=i;
//开始频谱校正
if((k!
=0)|(k!
=(NN/2-1)))
a0=x[0][k]-x[0][k-1];
a1=x[0][k]-x[0][k+1];
Nf=k;
if(a0<
a1)
Nf=Nf-x[0][k-1]/(x[0][k-1]+x[0][k]);
//频率校正
max=(x[0][k-1]*(k-1)+x[0][k]*k)/Nf;
//幅值校正
if(a0>
Nf=Nf+x[0][k+1]/(x[0][k]+x[0][k+1]);
max=(x[0][k+1]*(k+1)+x[0][k]*k)/Nf;
tempfre=Nf*fs/NN;
//校正后的频率
amp_now=max*Amp_unit;
//校正后的幅值,其中Amp_unit是ADC输入的最大电压除以1024
程序CMD文件
/****************************************************************************/
/*volume.cmd-SamplelinkercommandfileforF28xxdevices*/
/**/
/*Description:
ThisfileisasampleF28xxlinkercommandfilethatcan*/
/*beusedforlinkingprogramsbuiltwiththeTMS320C2000*/
/*CCompiler.Useitasaguideline;
youmaywanttochange*/
/*theallocationschemeaccordingtothesizeofyour*/
/*programandthememorylayoutofyourtargetsystem.*/
-lrts2800_ml.lib
MEMORY
PAGE0:
PROG(R):
origin=0x3E8000,length=0x10000
BOOT(R):
origin=0x3FF000,length=0xFC0
RESET(R):
origin=0x3FFFC0,length=0x2
VECTORS(R)