加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

[TMS320C665x]06、FFT快速傅里叶变换与IFFT逆变换

(2016-05-24 12:57:36)
标签:

tms32c665x

ti

dsplib

fft

ifft

分类: ST/TI

利用TI DSPLIB很容易实现FFT 与IFFT








#include                   // C 语言标准输入输出函数库
#include                    // C 数学函数库

#include "mathlib.h"                // DSP 数学函数库
#include "dsplib.h"                 // DSP 函数库






// 软件断点
#define SW_BREAKPOINT     asm(" SWBP 0 ");

// 快速傅里叶变换
// π 及 浮点数极小值
#define PI                3.141592654
#define F_TOL             (1e-06)






// 快速傅里叶变换测试
// 测试快速傅里叶变换点数
// 注意:TI DSP库 最大支持一次性计算 256K 个实数点的 FFT
#define N 1024
// 采样频率
#define Fs 1000.0
// 信号
#pragma DATA_ALIGN(Input, 8);
float Input[2 * N];
// 信号 副本
float InputOrig[2 * N];
// FFT 输出
#pragma DATA_ALIGN(FFT_Out, 8);
float FFT_Out[2 * N];
// IFFT 输出
#pragma DATA_ALIGN(IFFT_Out, 8);
float IFFT_Out[2 * N];

// 旋转因子
#pragma DATA_ALIGN(W, 8);
float W[2 * N];

// 二进制位翻转
#pragma DATA_ALIGN (brev, 8);
unsigned char brev[64] =
{
    0x00, 0x20, 0x10, 0x30, 0x08, 0x28, 0x18, 0x38,
    0x04, 0x24, 0x14, 0x34, 0x0c, 0x2c, 0x1c, 0x3c,
    0x02, 0x22, 0x12, 0x32, 0x0a, 0x2a, 0x1a, 0x3a,
    0x06, 0x26, 0x16, 0x36, 0x0e, 0x2e, 0x1e, 0x3e,
    0x01, 0x21, 0x11, 0x31, 0x09, 0x29, 0x19, 0x39,
    0x05, 0x25, 0x15, 0x35, 0x0d, 0x2d, 0x1d, 0x3d,
    0x03, 0x23, 0x13, 0x33, 0x0b, 0x2b, 0x1b, 0x3b,
    0x07, 0x27, 0x17, 0x37, 0x0f, 0x2f, 0x1f, 0x3f
};










// 产生旋转因子
void tw_gen(float *w, int n)
{
    int i, j, k;

    for(i = 1, k = 0; i < n >> 2; i++)
    {
        w[k    ] = sin(2 * PI * i / n);
        w[k + 1] = cos(2 * PI * i / n);

        k += 2;
    }

    for(j = 1; j <= n >> 3; j = j << 2)
    {
        for(i = 0; i < n >> 3; i += j)
        {
            w[k]     = (float)sin( 4 * PI * i / n);
            w[k + 1] = (float)cos( 4 * PI * i / n);
            w[k + 2] = (float)sin( 8 * PI * i / n);
            w[k + 3] = (float)cos( 8 * PI * i / n);
            w[k + 4] = (float)sin(12 * PI * i / n);
            w[k + 5] = (float)cos(12 * PI * i / n);

            k += 6;
        }
    }
}

void tw_geni(float *w, int n)
{
    int i, j, k;

    for(i = 1, k = 0; i < n >> 2; i++)
    {
        w[k    ] =  sin (2 * PI * i / n);
        w[k + 1] = -cos (2 * PI * i / n);

        k += 2;
    }

    for(j = 1; j <= n >> 3; j = j << 2)
    {
        for(i = 0; i < n >> 3; i += j)
        {
            w[k]     = (float) -sin ( 4 * PI * i / n);
            w[k + 1] = (float)  cos ( 4 * PI * i / n);
            w[k + 2] = (float) -sin ( 8 * PI * i / n);
            w[k + 3] = (float)  cos ( 8 * PI * i / n);
            w[k + 4] = (float) -sin (12 * PI * i / n);
            w[k + 5] = (float)  cos (12 * PI * i / n);

            k += 6;
        }
    }
}






int main(void)
{
    // 产生待测试信号
    unsigned int i;
    for (i = 0; i < N; i++)
    {
        Input[i] = 5 * sin(2 * PI * 150 * (i / Fs)) + 15 * sin(2 * PI * 350 * (i / Fs));
    }

    // 基
    unsigned char rad;
    if(N == 64 || N == 256 || N == 1024 || N == 4096 || N == 16384 || N == 65536)
    {
        rad = 4;
    }
    else if(N == 32 || N == 128 || N == 512 || N == 2048 || N == 8192 || N == 32768)
    {
        rad = 2;
    }
    else
    {
        printf ("不支持计算 %d 点快速傅里叶变换!\n", N);

        while(1);
    }

    // 保留一份输入信号副本
    memcpy(InputOrig, Input, 2 * N * sizeof(float));

    // 产生旋转因子
    tw_gen(W, N);

    // FFT 计算
    DSPF_sp_fftSPxSP_r2c(N, Input, W, FFT_Out, brev, rad, 0, N);

    // 计算振幅
    float mo[2 * N];
    for(i = 0; i < N; i++)
    {
        if(i == 0)
        {
            mo[i] = mo[i] / N;
        }
        else
        {
            mo[i] = sqrtsp(powsp(FFT_Out[2 * i], 2) + powsp(FFT_Out[ 2 * i + 1], 2));
            mo[i] = mo[i] * 2 / N;
        }
    }

    // 产生旋转因子
    tw_geni(W, N);

    // IFFT 计算
    DSPF_sp_ifftSPxSP_c2r(N, FFT_Out, W, IFFT_Out, brev, rad, 0, N);

    for(i = 0; i < N; i++)
    {
        if(abs(IFFT_Out[i] - InputOrig[i]) > F_TOL)
        {
            printf("失败 M 原始数据 .5f 逆变换 .5f\r\n", i, InputOrig[i], IFFT_Out[i]);
        }
    }

    // 断点
    SW_BREAKPOINT;
}

 

 

http://s8/middle/002jCVK0zy71VMp8CEL87&690

http://s8/middle/002jCVK0zy71VMoZlv937&690

Matlab代码

fs=1000;                                     % 采样频率

N=1024;                                      % 数据点数

n=0:N-1;t=n/fs;                              % 时间序列

x=5*sin(2*pi*150*t)+15*sin(2*pi*350*t);      % 信号

subplot(2,1,1),plot(t,x);                    % 绘制时域信号图

y=fft(x,N);                                  % 对信号进行快速傅里叶变换

mag=abs(y);mag=mag*2/N;                      % 振幅

f=n*fs/N;                                    % 频率序列

subplot(2,1,2),plot(f,mag);                  % 绘制振幅图

xlabel('频率/Hz');

ylabel('振幅');title('N=1024');grid on;

grid on;                                     % 绘制振幅图

http://s16/middle/002jCVK0zy71VMpuOUTef&690

原地址:http://blog.sina.com.cn/s/blog_7e7fa4c80102wiyx.html

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有