FFT在DSP28335中的使用

引言:

在做谐波提取的过程中,用到了FFT,由于开关频率的限制,最开始考虑的是DFT以及滑窗DFT,之后又考虑过FFT。过程中走了许多弯路,记录之!

1.傅里叶变换理论知识

1.1傅里叶级数

引用矩阵里面基的概念,一个非周期信号,可以用泰勒级数去展开,所选取的幂次信号就是一组基底,系数则是权重;于此对应,一个周期信号,就可以选取不同频率的正余弦信号作为基底,进行表示,从而得到傅里叶级数展开;展开的系数可以通过基底之间的正交性,从而两边分别乘以对应基底得到!

1.2傅里叶变换周期与离散的关系

傅里叶变换定义:

傅里叶变换定义的最原始适用范围是连续非周期时间信号,得到的频域信号就是连续非周期的;如果时域进行周期化,则频域就离散化,这就是傅里叶级数;如果时域进行离散化,则频域就周期化,这就是采样定理的由来;如果同时对时域进行离散化和周期化,则频域也会相应的周期化和离散化,这就是离散傅里叶变换DFT的由来;

1.3离散傅里叶变换

离散傅里叶变换的定义:

用矩阵表示如下:


1.4FFT

DFT用于信号处理,时间复杂度是O(N2),开销过大;利用数字信号处理里面的提取公因子、合并同类项的做法,不断二分,最后可以得到快速傅里叶变换,即时域基2的蝶形法,还有基4等方法。

FFT对信号要求是2的幂次,这也是它的一个限制地方

1.5滑窗DFT

针对FFT无法克服的对采样数目的限制,有的时候采取改进的滑窗DFT更加有利,并且DFT是并行算法!

2.在28335中实现

2.1DFT

DFT的程序,按照定义翻译成C语言即可;使用循环来计算每一次谐波的实部和虚部;虽然定义是N*N的矩阵,但是推到可以发现X(N-m)=X(m),也就是说,N个数,只能算出前N/2次的信号:


2.2FFT_自己实现

FFT按照蝶形运算的定义,分为两步:第一步,将输入数据进行换位处理,自己之前使用了一个迭代不断二分来换位,后来发现网上给的另一种算法简单多了,这建立在理解的基础上;第二步,就是进行一个三重循环,即可得到频域信号的实部和虚部;

在得到实部和虚部的基础上,可以求幅值和相角,也可以直接得到时域信号,这一点自己走了很多弯路——认为要求出幅值和相角,然后才能求出时域信号,其实只要只要:实部*cos(nwt)+虚部*sin(nwt)即可:

自己写的换位程序:



换位之后的蝶形运算程序:



在最后那个循环中四行代码中,自己敲了第一行,就进行了复制粘贴,由于其中一个变量没有改正,导致卡了很久——虽然你可以多次烧写和调试,但是时间是没有多次的,所以一定要逻辑严密!

2.3单点滑窗DFT

DFT相邻两个周期(0-255点和1到256点)之间,含有大量相同信息,如果提取这些信息保存,则可以大大减少第二次的计算量,这就是滑窗DFT的思想由来。

具体内容参照硕士论文《滑动DFT算法研究_黄寒华》。代码如下:


2.4多点滑窗


这个代码也卡了两天,就出在那个real已经被替换了,但是万分纠结,各种公式检查都没有问题,甚至怀疑那个公式错了,最后发现竟然是这个覆盖问题。

刚开始以为多点滑窗会快一点,后来发现,四点滑窗的时间比四个单点划窗的时间更长,复杂性可以从公式看出来:


2.5FFT调用库函数

28335中调用库函数的配置如下:

参照文档:

TI官网:C28x_FPU_Library_Beta1

库函数:

包含进去“C28x_FPU_Lib.lib”

头文件:

包含进去:#include “FPU.h”

CMD文件指定内存分配:


原文件里面指定指定分配:


FFT计算过程:


其他计算幅值、相角、归一化等函数,参照以上参考文档;

2.6FFT时间分析及改进算法

在文档中提到的基准时间,均是指其中某一语句的开销:


运算相位的时间明显比运算幅值的时间大了一个数量级,因为相位是actan(实部/虚部),除法会特别慢;


自己当时在从实部和虚部到幅值的过程中,使用了除以256,导致时间比乘以256分之一慢了近十倍,值得注意;

另外,针对求出实部虚部后,再求出幅值和相角,再去求时域信号值,这个相角花费了巨大时间,可以改进的方法是:推导DFT公式,将得到的FFT虚部和实部,从N/2填充,实部偶对称,虚部奇对称,然后再讲得到的填充实部和虚部分别进行变换,得到时域值,这种方法只需要三个FFT,外加一些填充,总共210us即可实现!












你可能感兴趣的:(FFT在DSP28335中的使用)