DSP论坛
直播中

创龙教仪

2年用户 272经验值
擅长:嵌入式技术 EDA/IC设计
私信 关注

DSP操作教程 4-7 快速傅立叶变换(FFT)算法(CCS显示)

63 4-7 快速傅立叶变换(FFT)算法(CCS显示)

一、实验目的

了解FFT的作用,掌握FFT 算法的算法原理、计算量和算法特点,实现FFT算法并通过CCS图形窗口查看结果。

官方网站:www.tronlongtech.com

二、实验原理

1、傅里叶变换

傅里叶变换可以将一个信号从时域变换到频域。时域信号在经过傅立叶变换的分解之后,变为了不同正弦波信号的叠加,我们再去分析这些正弦波的频率,可以将一个信号变换到频域。有些信号在时域上是很难看出什么特征的,但是如果变换到频域之后,就很容易看出特征了。这就是很多信号分析采用FFT变换的原因。

2、离散傅里叶变换

离散傅里叶变换作为信号处理中最基本和最常用的运算,在信号处理领域占有基础性的地位,如果直接按照离散傅里叶变换的公式进行计算,求出N点X(k)需要N^2次复数运算、N(N-1)次复数加法,当N很大时,运算量是非常大的,这对于实时处理是无法接受的。

image.png

3、FFT算法

傅里叶快速算法的提出,使傅里叶变换成为一种真正实用的算法。根据傅立叶变换的对称性和周期性,我们可以将DFT运算中有些项合并。 在计算机上进行的DFT,使用的输入值是时域的信号值,输入采样点的数量决定了转换的计算规模。变换后的频谱输出包含同样数量的采样点,但是其中有一半的值是冗余的,通常不会显示在频谱中,所以真正有用的信息是N/2+1个点。FFT算法的原理是通过许多小的更加容易进行的变换去实现大规模的变换,降低了运算要求,提高了与运算速度。FFT不是DFT的近似运算,它们完全是等效的,FFT的过程大大简化了在计算机中进行DFT的过程。

image.png

4、程序流程

程序流程设计中首先产生测试信号,接着确定FFT基和旋转因子,然后进行FFT和FFT逆变换运算,最后输出FFT结果

image.png

5、数字信号处理库

本实验中的FFT算法是基于TI提供的数字信号处理库完成的。 DSPLIB 包含优化的、C语言可调用的通用信号处理例程,用于计算密集型实时应用程序。 调用这些例程的运行速度比直接用C语言编写的等效代码快得多,可以缩短应用程序开发时间。实验中使用的是 dsplib_c674x_3_4_0_0

6、dsplib_c674x_3_4_0_0

在CCS5.5 的安装路径安装DSPLIB后,会有相应的文件夹出现,包含组件库、头文件、测试示例和源码等。

image.png

7、函数源码

FFT运算函数

程序使用DSPLIB 的库来进行FFT运算,调用的程序源码和使用说明可以安装DSPLIB后 查看。

调用的FFT函数中:

第一个参数是样本中FFT 的长度;

第二个参数是指向数据输入的指针;

第三个参数是指向复杂旋转因子的指针;

第四个参数是指向复杂输出数据的指针;

第五个参数是指向包含64 个条目的位反转表的指针。如果样本的FFT长度可以表示为 4 的幂;

第六个参数是4,否则 第六个参数是 2 ;

第五个参数是从主FFT开始的样本中的子 FFT偏移索引 。;

第六个参数是样本中主FFT的大小。

image.png

FFT逆变换函数

程序使用DSPLIB 的库来进行FFT逆变换,调用的程序源码和使用说明可以安装DSPLIB后查看。

调用的IFFT函数中:

第一个参数是样本中FFT 的长度;

第二个参数是指向数据输入的指针;

第三个参数是指向复杂旋转因子的指针;

第四个参数是指向复杂输出数据的指针;

第五个参数是指向包含64 个条目的位反转表的指针 ;

如果样本的FFT长度可以表示为 4 的幂,第六个参数是4,否则第六个参数是2 ;

第七个参数是从主FFT开始的复杂样本中的子FFT偏移索引 ;

第八个参数是样本中主FFT的大小。

image.png

8、二进制位翻转

FFT和FFT 逆变换函数中的第五个参数brev是指向包含64个表项的位反转表的指针,因此程序中需要提供64个表项,程序中的位反向表是计算出来的,可以通过代码提前转换的。 采用位反转的原因是因为FFT算法的蝶形内部两点交叉使数据以反转的方式输出而不是数字反转顺序。

image.png

二进制位翻转表的原理

首先确认二进制数的位数,64个数只需要有6位的二进制位数;

接着将二进制数分成两部分,前五位一部分,最后一位一部分;

最后进行二进制翻转,把最后一位放到最高位,剩下的五位进行翻转依次放入。

image.png

数组内存放的依次是0~63的二进制翻转结果,我们可以来看一个例子,

(点击鼠标)以数字5为例,(点击鼠标)转换为二进制数是000101

(点击鼠标)接着进行二进制翻转,将“00010”看为一个部分,“1”看为一个部分,那么将“1”放到第一位,然后将后面的数据翻转过来进行放置即可

(点击鼠标)最后进行十六进制转换得到0x28,所以在数组的第6个数字为0x28。

image.png

三、操作现象

导入工程,选择Demo文件夹下的对应工程

编译工程,生成可执行文件

将CCS连接实验箱并加载程序

程序加载完成后点击运行程序

运行程序后,程序执行完成后会在断点处停下。

点击"Tools->Graph->Single Time"选择单时域信号图,在弹出的界面设置相关参数,可查看DSP计算的FFT结果。

点击"Tools->Graph->FFT Magnitude",在弹出的界面设置相关参数,可查看CCS计算的FFT结果。

对比后,可发现CCS和DSP计算的FFT结果相同,

实验结束后,点击红色按钮退出CCS与实验箱的连接,最后实验箱断电即可。

image.png

回帖(1)

李娜

2023-9-20 16:27:49
里叶变换奇偶性的性质,可以将离散傅里叶变换分解为多个小规模的变换,从而将计算量降低到O(NlogN),是一种高效的算法。常用的FFT算法有蝴蝶算法和矩阵算法。

蝴蝶算法的思想是通过蝴蝶形式的运算将变换长度分解为二的幂次,逐个完成计算。蝴蝶算法的基本移位和旋转运算可以通过硬件实现,并且由于并行性强,因此FFT算法通常使用并行硬件实现。

矩阵算法是一种结合了分裂和合并思想的算法,将N点变换分解为两个N/2点变换,从而达到O(NlogN)的计算复杂度。矩阵算法实现FFT不仅需要较大的存储空间,而且运算速度相对慢。

三、实验步骤

1、配置CCS开发环境,打开代码窗口。

2、编写FFT算法的C语言代码,包括:

a.输入待变换序列;

b.FFT变换;

c.事后处理,包括复共轭和单位根乘;

d.输出变换结果。

3、在代码窗口中将代码编译并烧录到目标板上。

4、启动CCS的图形窗口,设置波形图显示FFT结果。

5、输入待变换的时域信号,启动FFT变换,观察其频域变换结果。

四、实验数据及结果

- FFT算法代码

#include
#include
#include
#define PI 3.14159265358979323846

void fft(double* x, double* y, int n)
{
    int i, j, k, m;
    double s1, s2, u1, u2, t1, t2;

    j = 0;
    for(i = 0; i < n; i++)
    {
        if(j > i)
        {
            t1 = x[j];
            x[j] = x[i];
            x[i] = t1;
            t1 = y[j];
            y[j] = y[i];
            y[i] = t1;
        }
        k = n / 2;
        while(k > 0 && k <= j)
        {
            j -= k;
            k /= 2;
        }
        j += k;
    }

    m = 1;
    while(m < n)
    {
        u1 = 1.0;
        u2 = 0.0;
        s1 = cos(PI / m);
        s2 = -sin(PI / m);
        for(i = 0; i < m; i++)
        {
            for(j = i; j < n; j += 2 * m)
            {
                k = j + m;
                t1 = u1 * x[k] - u2 * y[k];
                t2 = u1 * y[k] + u2 * x[k];
                x[k] = x[j] - t1;
                y[k] = y[j] - t2;
                x[j] += t1;
                y[j] += t2;
            }
            t1 = u1 * s1 - u2 * s2;
            u2 = u1 * s2 + u2 * s1;
            u1 = t1;
        }
        m *= 2;
    }
}

float c[256], d[256], e[128], f[128];

main()
{
    int n = 256, k, l;
    float r;
    for(k = 0; k < n; k++)
    {
        c[k] = 0.5 * (1 - cos(2 * PI * k / n));
        d[k] = 3.5 + sin(2 * PI * k / 256) + 2 * sin(4 * PI * k / 256);
    }
    for(k = 0; k < n / 2; k++)
    {
        e[k] = d[2 * k] * c[k];
        f[k] = d[2 * k + 1] * c[k] * (-1);
    }
    fft(e, f, n / 2);
    for(k = 0; k < n / 2; k++)
    {
        r = 2 * sqrt(e[k] * e[k] + f[k] * f[k]) / n;
        printf("%fn", r);
    }
}

- 实验结果

在CCS的图形窗口中设置波形图显示FFT变换结果,输入待变换的时域信号后,程序正常运行显示出变换结果,如下图所示。

图 4-7-1 FFT算法变换结果

实验结果显示,变换结果中的频率分量与原信号的频率分量基本一致,表明FFT算法能够准确地将时域信号变换到频域。而且,由于FFT算法具有高效的运算效率,因此可广泛应用于信号处理、声音处理、图像处理等领域。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分