有问题就解决问题之TI库实现2048点或更大点数FFT_天涯博客_有见识的人 ...

TI提供的FFT库(sprc081)使用起来很方便,只要直接调用即可;更重要的是其中做了好些优化,而且是用汇编写成,运算速度肯定要比自己写的C代码更快好多。这个库{zd0}能运算1024点的实数FFT,但实际中我们可能还需要更大点数的FFT,那如何去修改呢?其实修改的地方并不多,以前我曾花了一段时间浏览了一下那些头疼的汇编代码,发现模块化写得很好啊(佩服TI的工程师!),这样修改起来就快多了。
1. 2048点FFT
直接在工程中加入原来的库文件fft.lib,并在代码中作如下修改:
{dy}步:在有关FFT代码的头文件fft.h中增添如下一段代码:

#define RFFT32_2048P_DEFAULTS { (long *)NULL,\
 (long *)NULL,\
 1024,\
 10,\
 (long *)NULL,\
 (long *)NULL,\
 0,\
 0,\
 1,\
 (void (*)(void *))CFFT32_init,\
 (void (*)(void *))CFFT32_calc,\
 (void (*)(void *))RFFT32_split,\
 (void (*)(void *))RFFT32_mag,\
 (void (*)(void *))RFFT32_win}

结构体RFFT32关键说明:
1. {dy}个(long *)NULL,\,是计算缓冲区(ipcb)的指针;
2. 第二个(long *)NULL,\,是查表旋转因子(ft)的指针;
3. 1024指的是FFT的大小,注意这里是2048点实数FFT被打包成1024点的复数,这是这个库的实数FFT运算的特点,这样节省一半运算时间和存储空间;
4. 10即1024是2的10次方,因为这里采用的是基2时间抽取算法;
5. 下面的两个(long *)NULL,\分别是运算结果中存放幅值(mag)以及加窗表格(win)的指针;
6. 下面的两个0分别是计算结果中的峰值幅值与峰值频率,这里初始化0;
7. 下面的1指的是查表的步进值,因在这个sprc081文档的库已经有Q31格式(以及Q30格式)的1024点的正弦因子表,因此对于1024点复数FFT查表步进值设为1即可。
8. 下面其他的就是要调用的函数指针了,不再赘述。

明白上述结构体的定义后,改写其他点数就很容易了,比如这个库最少能做到128点的实数FFT,我们还可以相应改成64点或者更低点数的实数FFT,比如64点的结构体就是如下的一段:

#define RFFT32_64P_DEFAULTS { (long *)NULL,\
 (long *)NULL,\
 32,\
 5,\
 (long *)NULL,\
 (long *)NULL,\
 0,\
 0,\
 32,\
 (void (*)(void *))CFFT32_init,\
 (void (*)(void *))CFFT32_calc,\
 (void (*)(void *))RFFT32_split,\
 (void (*)(void *))RFFT32_mag,\
 (void (*)(void *))RFFT32_win}

第二步:修改源程序代码里的变量定义:
#include "fft.h"
#define N 2048 //定义N的点数,2048点
//分别在数据存储区为ipcb和mag分配足够的地址,具体见下面的连接器文件
#pragma DATA_SECTION(ipcb, "FFTipcb");
#pragma DATA_SECTION(mag, "FFTmag");
//定义变量
RFFT32 fft=RFFT32_2048P_DEFAULTS;
long ipcb[N+2];
long mag[N/2+1];

//其他部分函数调用都是一样的,这里不再列出

第三步:在连接器(.cmd)文件里分配存储地址:
这里给出我在2808上的分配方法:
MEMORY
{
PAGE 1 :
 L0L1RAM : origin = 0x00B000, length = 0x001000
 HL0SARAM : origin = 0x3F8000, length = 0x001010
 DRAMH0 : origin = 0x3F9010, length = 0x000ff0

}
SECTIONS
{
 FFTipcb ALIGN(4096): { }> HL0SARAM, PAGE = 1
 FFTtf :> DRAMH0 , PAGE = 1
 FFTmag :> L0L1RAM, PAGE = 1
}
好,到此为止就修改好了,可以使用这个FFT库实现2048点实数FFT了。

2. 4096点或更大点数的FFT
{dy}步:修改汇编代码并制成库文件
其实要实现4096点的FFT需要改动的地方也不多,主要因为原来的这个库只提供了1024点的正弦值,我们需要自己算出2048点的Q31(或Q30)格式的一周期正弦值,并将其代替原来汇编代码里的1024点的表格。汇编代码的其他地方不需要改动,不然可能产生不可预知的后果。
在汇编代码文件sel_q.asm里查看设置:
; Select Twiddle factor Q format
TF_QFMAT .set Q30
若是TF表设为Q30,则只需将计算出的正弦值移位成Q30格式即可。另外需注意的是,2048点的FFT需要2048点的TF表,但这个库将其优化成只需2048×3/4 = 1536点,即1.5K大小的表格(见sprc081文档第10页,注意到正弦的第二部分与余弦的{dy}部分是相重合的,这样便节省了1/4周期的点数)。计算好正弦值并加入到汇编代码里,然后将所有的汇编代码导进CCS里做成一个新的库,到时直接添加到工程里调用。
为了方便这里我已将其做成一个新的库命名为FFT_new.lib,大家直接用即可。

第二步:修改头文件fft.h 结构体定义
增添如下一段代码:
#define RFFT32_4096P_DEFAULTS { (long *)NULL,\
 (long *)NULL,\
 2048,\
 11,\
 (long *)NULL,\
 (long *)NULL,\
 0,\
 0,\
 1,\
 (void (*)(void *))CFFT32_init,\
 (void (*)(void *))CFFT32_calc,\
 (void (*)(void *))RFFT32_split,\
 (void (*)(void *))RFFT32_mag,\
 (void (*)(void *))RFFT32_win}

第三步:修改变量定义和变量存储地址
这里修改的方法与上述相同,不再赘述。必须注意的是对于32位的4096点的FFT,其缓冲区占用8K连续地址,因此分配地址需考虑周全。这里给出我在2808上的一种分配方法。
F2808的片内18K单周期访问RAM按地址连续而言分成两块,即M0、M1的0x0000-0000~0x0000-07FF以及L0、L1、H0的0x0000-8000~0x0000-BFFF(同时映射到地址0x003F-8000~0x003F-BFFF)。M0、M1地址用作未初始化段及堆栈段等,因此只能选用L0等大段RAM空间;另外FFT查表所需的旋转因子常数也需保存在不受冲突的RAM或Flash中。这两段所需的地址大小就有11K×16,同时还需为程序代码和其他数据变量分配足够的存储段。为了优化并节省空间,这里没有采用加窗方法,并且将计算缓冲区(ipcb)和结果区(mag)设为同一地址(不然的话还真没法分配):
MEMORY
{
PAGE 0 :
 PRAMH0 : origin = 0x00AC04, length = 0x0013FC
 FFT_TF : origin = 0x00A004, length = 0x000C00
PAGE 1 :
 FFT_IPCB : origin = 0x008000, length = 0x002004
}
SECTIONS
{
 .text : > PRAMH0, PAGE = 0
 FFTipcb ALIGN(8192): { }> FFT_IPCB, PAGE = 1
 FFTtf :> FFT_TF , PAGE = 0
}


我用的2808片内只含18K 的RAM,只用这些RAM对于超过4096点的FFT已经难以实现了。
若是需要做加窗的话,需要自己计算出4096点的窗系数并代替头文件里的窗系数;另外,对于8192点或更大的FFT,改编方法与上述类似。






郑重声明:资讯 【有问题就解决问题之TI库实现2048点或更大点数FFT_天涯博客_有见识的人 ...】由 发布,版权归原作者及其所在单位,其原创性以及文中陈述文字和内容未经(企业库qiyeku.com)证实,请读者仅作参考,并请自行核实相关内容。若本文有侵犯到您的版权, 请你提供相关证明及申请并与我们联系(qiyeku # qq.com)或【在线投诉】,我们审核后将会尽快处理。
—— 相关资讯 ——