转载自:http://blog.csdn.net/aeecren/article/details/67644363;个人觉得写的很详细,值得一看

在数字信号处理中,FFT变换是经常使用到的,在DSP中自己编写的FFT变换函数通常会存在计算效率太慢的问题,有时需要调用DSP函数库自带的变换函数。但是,DSP在对FFT运算效率优化的同时,对于函数的调用方式也就有了比较多的要求,下面结合自己的调试经验做一下简单的介绍。

1、准备工作

DSP的数字信号处理的一系列函数都在C28x_FPU_Lib.lib库中,因此,首先需要在CCS的工程文件中连接此库:在工程设置中C2000 Linker——file search path中添加该库和路径。并在主程序中包含下面头文件:#include "FPU.h"。

2、结构体介绍

FFT函数的输入为一个结构体,该结构体的定义方式如下:

typedef struct 
{ float32 *InPtr; 
  float32 *OutPtr;
  float32 *CoefPtr; 
  float32 *CurrentInPtr;
  float32 *CurrentOutPtr; 
  Uint16 Stages; 
  Uint16 FFTSize; 
} CFFT_F32_STRUCT;

其中InPtr为输入数组指针,假设你的CFFT的采样点1024个点,那么你的输入数组为inputdata[2*FFTSize],长度为2048是因为输入数据为复数,实部和虚部需要分开进行存储的,所以输入数组的长度为2*FFTSize.其中实部和虚部的存储方式为inputdata[0]存储你第一点的实部,inputdata[1]存储第一点的虚部,接着依次向下inputdata[2]存储第二个点的实部,inputdata[3]第二个点的虚部。

OutPtr为指向输出数组的指针,输出数组的大小也为2*FFTSize,存储方式同样的outputdata[0]。

CoefPtr,为指向转化因子数组的指针,长度为FFTSize,决定傅里叶转化因子的只有傅里叶变换的阶数。

CurrentInPtr也是指向输入数组的指针,但是该输入数组是用来计算幅值所用的。

CurrentOutPtr来指向幅值输出的数组。

stage为傅里叶变换的阶数。

FFTSize为FFT变换的长度,也就是常说的多少点的FFT变换,其与阶数的关系为FFTSize=2^stage。
3、函数介绍

下面介绍一下各个函数的应用:
    第一个函数是: CFFT_f32_sincostable(&cfft)

其中cfft就是上述的一个结构体。这个函数的作用就是计算傅里叶变换的转化因子。转化因子由公式可知只与傅里叶变换的阶数有关,所以只要在结构体中对stage和FFTSize进行了赋值就可以计算转化因子了,而且转化因子是固定的,如果不需改变傅里叶变换的阶数,只需要计算一次就好了。

第二个函数是:  CFFT_f32(&cfft)

这个函数就是做复数傅里叶变换的函数,需要注意的是该函数要求输入数组的数据格式对齐,即变量存储的起始地址为2*FFTsize*sizeof(float),实现方式在下面3中定义。如果数据格式不对齐,则该函数的计算结果不定。

第三个函数是:
CFFT_f32u(&cfft)

这个函数同样是做FFT变换的,但是其不要求输入数据的格式对齐,适用于输入数据格式比较乱时,但是同样相对与前一个函数来说,其计算效果会比较差。

第四个函数为 : CFFT_f32_mag(&cfft)

这个函数是计算幅值的函数,主要作用就是计算*CurrentInPtr指向的复数数组中的复数的模值,将计算出来的模值保存在*CurrentOutPtr该成员指向的数组中,与其他成员无关。
    最后一个函数是:  ICFFT_f32(&cfft)

该函数计算FFT的逆变换。同样要求输入数组格式对齐。

4、 格式对齐的实现方式

前面介绍的CFFT和ICFFT函数都要求输入的数组格式对齐,即变量存储的起始地址为2*FFTsize*sizeof(float)。例如256点的FFT变换,则变量的起始地址必须是1024的倍数。格式对齐的方式利用变量定义的方式进行。

首先确定变量存储的区域,该代码与普通对存储空间分区的代码无区别,只是定义一个区域用来存储自己定义的变量:

ZONE6C     : origin = 0x108000, length = 0x004000

然后在上面存储分区中定义变量存储的段,用来定义后续变量的具体位置,ALIGH的作用就是使该段的起始地址为2*FFTsize*sizeof(float)的倍数,但是其功能也仅仅如此,如果在该段中定义了多个变量,则不能保证每个变量的起始地址均为1024倍数。因此一般一个段只定义一个变量,可以在同一个区中定义出多个段,从而实现多个变量的定义。如下面例子中,在ZONE6C区中定义了四个段,每个段首地址均为1024的倍数。

ZONE6FFTinDATA            : > ZONE6C,    PAGE = 1     ALIGN(1024)

ZONE6w_change_DATA        : > ZONE6C,    PAGE = 1     ALIGN(1024)

ZONE6x_frequency_amp      : > ZONE6C,    PAGE = 1     ALIGN(1024)

ZONE6FFToutDATA           : > ZONE6C,    PAGE = 1     ALIGN(1024)

然后定义变量所在的段,每个变量占了一个段:

#pragma DATA_SECTION(fft_data_1024,"ZONE6FFTinDATA");

#pragma DATA_SECTION(CFFToutBuff,"ZONE6FFToutDATA");

#pragma DATA_SECTION(x_frequency_amp_1024,"ZONE6x_frequency_amp");

#pragma DATA_SECTION(W_fft_change,"ZONE6w_change_DATA");

最后定义变量类型和大小:

float32    fft_data_1024[512];             //定义FFT内部变换使用的复数数组

float32    CFFToutBuff[512];              //定义FFT处理复数结果数据

float32 W_fft_change[256];

float32 x_frequency_amp_1024[256];     //定义FFT处理幅值结果数据

通过上面的定义的方式实现了对于变量格式对齐的定义。

最新文章

  1. Android图片缓存之Bitmap详解
  2. jquery用一个事件控制另一个事件是否执行(不是删除事件)
  3. 用JS识别各版本浏览器
  4. [.net 面向对象程序设计进阶] (7) Lamda表达式(三) 表达式树高级应用
  5. 【知识积累】DES算法之C#加密&Java解密
  6. emacs 新手笔记(二) —— 分割窗格 (split window)
  7. VC++ chap13 文档与串行化
  8. 完全备份ORACLE数据库 并在另一台电脑上恢复
  9. SAP-MM:创建采购组织、采购组
  10. RSA不对称加密,公钥加密私钥解密,私钥加密公钥解密
  11. Objective-C分类 (category)和扩展(Extension)
  12. jquery获取当前选项的属性值a
  13. SQL Server 行转列,列转行。多行转成一列
  14. Python基础——输出[print()]与输入[input()]
  15. svn提交代码时不要提交bulid里的内容,会报错
  16. nyoj 正数性质
  17. div 光标处插入内容
  18. ABAP-动态ALV
  19. PAT甲 1001. A+B Format (20) 2016-09-09 22:47 25人阅读 评论(0) 收藏
  20. UR5 改造

热门文章

  1. flask-login模块
  2. js 变量作用域
  3. redis主从同步故障切换及集群配置
  4. 【笔记】Nginx热更新相关知识
  5. UVALive - 5857 Captain Q's Treasure
  6. 换行符java去除字符串中的空格、回车、换行符、制表符
  7. CPU利用率和CPU负荷(CPU usage vs CPU load)
  8. 浅谈Pool对象
  9. .NetCore WebApi
  10. SpringBoot+mybatis:报错Fri Oct 19 14:29:24 CST 2018 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requiremen