快速傅立叶变换FFT的实现DSP实验报告.docx
《快速傅立叶变换FFT的实现DSP实验报告.docx》由会员分享,可在线阅读,更多相关《快速傅立叶变换FFT的实现DSP实验报告.docx(10页珍藏版)》请在冰豆网上搜索。
快速傅立叶变换FFT的实现DSP实验报告
快速傅立叶变换(FFT)的实现
一、实验目的
在数字信号处理系统中,FFT作为一个非常重要的工具经常使用,甚至成为DSP运算能力的一个考核因素。
FFT是一种高效实现离散付氏变换的算法。
离散付氏变换的目的是把信号由时域变换到频域,从而可以在频域分析处理信息,得到的结果再由付氏逆变换到时域。
本实验的目的在于学习FFT算法,及其在TMS320C54X上的实现,并通过编程掌握C54X的存储器管理、辅助寄存器的使用、位倒序寻址方式等技巧,同时练习使用CCS的探针和图形工具。
另外在BIOS子目录下是一个使用DSP/BIOS工具实现FFT的程序。
通过该程序,你可以使用DSP/BIOS提供的分析工具评估FFT代码执行情况。
二、实验原理
1)基2按时间抽取FFT算法对于有限长离散数字信号{x[n]},0≤n≤-1N,其离散谱{x[k]}可以由离散付氏变换(DFT)求得。
DFT的定义为:
X(k)x[n]eNk0,1,...,N1n0
可以方便的把它改写为如下形式:
N1
nk
X(k)x[n]WnNkk0,1,...,N1
n0
不难看出,WN是周期性的,且周期为N,即
(nmN)(klN)nk
WNWNm,l0,1,2...
WN的周期性是DFT的关键性质之一。
为了强调起见,常用表达式WN取代W以便明确其周期是N。
2)实数FFT运算
对于离散傅立叶变换(DFT)的数字计算,FFT是一种有效的方法。
一般假定输入序列是复数。
当实际输入是实数时,利用对称性质可以使计算DFT非常有效。
一个优化的实数FFT算法是一个组合以后的算法。
原始的2N个点的实输入序列组合成一个N点的复序列,之后对复序列进行N点的FFT运算,最后再由N点的复数输出拆散成2N点的复数序列,这2N点的复数序列与原始的2N点的实数输入序列的DFT输出一致。
使用这种方法,在组合输入和拆散输出的操作中,FFT运算量减半。
这样利用实数FFT算法来计算实输入序列的DFT的速度几乎是一般复FFT算法的两倍。
本实验就用这种方法实现了一个256点实数FFT(2N=256)运算。
a.实数FFT运算序列的存储分配
如何利用有限的DSP系统资源,合理的安排好算法使用的存储器是一个比较
要的问题。
参见FFT实验程序的CMD文件:
MEMORY
PAGE0:
IPROG:
origin
=0x3080,
len
=0x1F80
VECT:
origin=
0x3000,
len=
0x80
EPROG:
origin=
0x38000,
len=
0x8000
PAGE1:
USERREGS:
origin
=0x60,
len
=0x1c
BIOSREGS:
origin=
0x7c,
len=
0x4
IDATA:
origin=
0x80,
len=
0xB80
EDATA:
origin=
0xC00,
len=
0x1400
}
SECTIONS
{
.vectors:
{}>VECTPAGE0
.sysregs:
{}>BIOSREGSPAGE1
.trcinit:
{}>IPROGPAGE0
.gblinit:
{}>IPROGPAGE0
.bios:
{}>IPROGPAGE0
frt:
{}>IPROGPAGE0
.text:
{}>IPROGPAGE0
.cinit:
{}>IPROGPAGE0
.pinit:
{}>IPROGPAGE0
.sysinit:
{}>IPROGPAGE0
.data
{}>EDATAPAGE1
.bss:
{}>IDATAPAGE1
.far:
{}>IDATAPAGE1
.const:
{}>IDATAPAGE1
.switch:
{}>IDATAPAGE1
.sysmem:
{}>IDATAPAGE1
.cio:
{}>IDATAPAGE1
.MEM$obj
:
{}>IDATAPAGE1
.sysheap:
{}>IDATAPAGE1
}
从上面的连接定位CMD文件可以了解到,程序代码安排在0x3000开始的存储器中。
其中0x3000-0x3080存放中断向量表。
FFT程序使用的正弦表、余弦表数据(.data段)安排在0xc00开始的地方。
变量(.bss段定义)存放在0x80开始的地址中。
另外,本256点实数FFT程序的输入数据缓冲为0x2300-0x23ff,FFT后功率谱的计算结果存放在0x2200-0x22ff中。
b.基二实数FFT运算的算法
该算法主要分为四步:
第一步,输入数据的组合和位倒序
第二步,N点复数FFT
第三步,分离复数FFT的输出为奇部分和偶部分
第四步,产生最后的N=256点的复数FFT结果
3)计算所求信号的功率
由于最后所得的FFT数据是一个复数,为了能够方便的在虚拟频谱仪上观察该
信号的特征,我们通常对所得的FFT数据进行处理——取其实部和虚部的平方和,
即求得该信号的功率。
power:
.asgAR2,AX
.asgAR3,OUTPUT_BUF
pshmar0
pshmbk
STM#d_output_addr,OUTPUT_BUF;AR3指向输出缓冲地址
STM#K_FFT_SIZE*2-1,BRC;块循环计数器设置为
255
指令
出缓冲中,
ANDM#7FFFH,*OUTPUT_BUF+;避免输出数据过大在虚拟示波器
;中显示错误
popmbk;保存各个寄存器值
popmar0
popmst0
power_end:
RET
注意,在上面的程序中将数据放回输出缓冲准备输出时使用了指令:
STHA,7,*OUTPUT_BUF
对accA左移7位是为了让显示的数据值在一个合适的范围内有利于观察显示的图形,由于所有的数据都左移了7位,所以从总体上看整个波形的性质还是一样的。
同时,由于有的数据太大,为了避免显示数据的溢出而导致在虚拟示波器中观察到的波形错误所以我们使用了指令:
ANDM#7FFFH,*OUTPUT_BUF+
来取出有效的数据位数。
三、实验内容
1)启动CCS,在Project菜单相项中打开FFT目录下的fft.pjt文件。
2)用鼠标展开左面项目栏,打开fft.asm源程序
3)使用Bulid命令完成编译、连接,并使用LoadProgram将生成的
fft.out装入5402片内存储器。
4)将光标移动到“callget_input行”,并设置一个探针点。
将光标移动到下一行“nop语”句,使用工具设置一个断点。
5)在File菜单中打开选项“FileI/O,使”用“AddFile在”FFT目录下打开数据文件fft.dat,然后修改“Address参”数为0x2300,修改“Length参”数为256。
这表示程序执行到探针点时,将从fft.dat文件中读出256个数据,并将数据放入0x2300开始的存储器中。
你可以选择“WrapAround”,循环使用该数据文件。
6)选择“AddProbePoint,”将探针点与数据文件连接起来。
选择探针点,然后在“Connect选”项中选择需要使用的数据文件名,再选择“Replace,”按确定键完成。
这时将返回图7所示的对话框。
你可以看到“Probe项”被自动修改为“Connected”,表示探针已经与数据文件成功相连。
7)完成探针设置后,可以使用F5或“Run”命令启动程序运行。
程序执行到探针点时自动从数据文件读出256个点的数据放入输入缓冲0x2300。
8)在“View菜”单项下选择“Graph->Time/Frequency,”打开一个图形工具以便显示输入数据波形。
将“StartAddress”改为0x2300,将“AcquisitionBufferSize改”为128,将“DSPDataType”改为“1-6bitsignedinteger,这”样即可显示128个输入点波形。
9)
调整窗口显示大小,将光标移动到源程序的“b_c_int00这”行,使用Debug中的“RuntoCursor项”,程序将执行到这行并停下。
这时FFT程序已经计算完成。
再打开一个波形显示窗口,这次仅仅将“StartAddress改为”0x2200,便可以显示计算完成后的谱波形。
10)选择“Debug下”的“Animate运”行程序,这时程序将循环运行,不断从数据文件fft.dat中读出数据,并计算其频谱。
这时你可以看到连续的输入/输出波形。
11)选择原始数据波形窗口,单击鼠标右键,进入“Properties属性”对话框。
你可以将“DisplayType”改为“FFTMagnitude”,这时输入数据将显示其频谱,对比两个图形,看看谱线的位置一样吗?
12)清除所有断点、探针点,关闭CCS的源程序窗口和上面的工程文件fft.pjt,然后在Project菜单下打开BIOS目录下fft.pjt文件。
这时一个使用DSP/BIOS工具实现FFT的例子。
为了使用DSP/BIOS的工具分析工具,我们将FFT的源程序做了一点修改。
将FFT子程序做为一个中断函数,并在DSP/BIOS的周期模块中调用。
所以在DSP/BIOS的配置文件中增加一个周期模块PRD0,并且设置每1ms执行一次,即每1ms执行一次FFT子程序。
。
这时的主程序仅仅完成一次数据输入,然后返回DSP/BIOS。
以后
DSP/BIOS将每隔1ms启动一次周期函数,完成一次FFT。
13)在File菜单中用LoadProgram装入BIOS目录下的demo5402.out文件。
参照前面的函数中的“callwait_input设”置一个探针点,并建立数据文件连接。
这时应该将输入数据读到0x2900开始的存储器中。
在FFT子程序process中设置一个断点,启动程序运行。
14)程序将在第一次进入周期函数执行FFT子程序时停下来。
使用
图形工具观察输入信号波形(启始地址0x2900)。
将FFT子程序执行完,然后再使用图形工具观察FFT后的波形(启始地址
0x2800)。
15)清除所有断点,以便程序连续运行。
使用Tools菜单下的DSP/BIOS选项打开“RTAControlPanel”窗口,再打开“ExecutionGraph”窗口。
在“RTAControlPanel”控制窗口中选择“enableSWIlogging”、“enablePRDlogging和“”gobalhostenable。
恢复”程序运行,观察FFT程序执行情况。
18)在Tools->DSP/BIOS->CPULoadGraph窗口,观察
CPU占用情况。
修改周期函数的周期,重新编译、连接、装入程序并运行,看看CPU占用比有何变化?