打印
[应用相关]

关于fft

[复制链接]
3006|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
liudewei|  楼主 | 2008-12-15 09:38 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
今天碰到一个问题,由于处理需要用到fft变换所以采用了一下的fft函数,函数在vc上运行正确,在我的ST STM32F10xxE上运行,结果运行函数不正确,应该是编译器的问题,但是不知道有什么方法可以修改一下函数使得结果正确,望高手解答,谢谢各位了!
(另外,stm32虽然出了函数库,但是fft的用于5.20版本的iar,实在是没有板子的驱动阿。。。。 )

// 入口参数: 
// l: l = 0, 傅立叶变换; l = 1, 逆傅立叶变换
// il: il = 0,不计算傅立叶变换或逆变换模和幅角;il = 1,计算模和幅角
// n: 输入的点数,为偶数,一般为32,64,128,...,1024等
// k: 满足n=2^k(k>0),实质上k是n个采样数据可以分解为偶次幂和奇次幂的次数
// pr[]: l=0时,存放N点采样数据的实部
// l=1时, 存放傅立叶变换的N个实部
// pi[]: l=0时,存放N点采样数据的虚部 
// l=1时, 存放傅立叶变换的N个虚部
//
// 出口参数:
// fr[]: l=0, 返回傅立叶变换的实部
// l=1, 返回逆傅立叶变换的实部
// fi[]: l=0, 返回傅立叶变换的虚部
// l=1, 返回逆傅立叶变换的虚部
// pr[]: il = 1,l = 0 时,返回傅立叶变换的模
// il = 1,l = 1 时,返回逆傅立叶变换的模
// pi[]: il = 1,l = 0 时,返回傅立叶变换的辐角
// il = 1,l = 1 时,返回逆傅立叶变换的辐角


void kbfft(double *pr,double *pi,int n,int k,double *fr,double *fi,int l,int il)

    int it,m,is,i,j,nv,l0;
    double p,q,s,vr,vi,poddr,poddi;
    
    //排序
    for (it=0; it<=n-1; it++) 
      { m=it; is=0;
        for (i=0; i<=k-1; i++)
          { j=m/2; is=2*is+(m-2*j); m=j;
            fr[it]=pr[is]; fi[it]=pi[is];
          }
      }
    
    //蝶形运算
    pr[0]=1.0; pi[0]=0.0;
    p=6.283185306/(1.0*n);
    pr[1]=cos(p); pi[1]=-sin(p);
    if (l!=0) pi[1]=-pi[1];
    for (i=2; i<=n-1; i++)
      { p=pr[i-1]*pr[1]; q=pi[i-1]*pi[1];
        s=(pr[i-1]+pi[i-1])*(pr[1]+pi[1]);
        pr=p-q; pi=s-p-q;
      }
    for (it=0; it<=n-2; it=it+2)
      { vr=fr[it]; vi=fi[it];
        fr[it]=vr+fr[it+1]; fi[it]=vi+fi[it+1];
        fr[it+1]=vr-fr[it+1]; fi[it+1]=vi-fi[it+1];
      }
    m=n/2; nv=2;
    for (l0=k-2; l0>=0; l0--)
      { m=m/2; nv=2*nv;
        for (it=0; it<=(m-1)*nv; it=it+nv)
          for (j=0; j<=(nv/2)-1; j++)
            { p=pr[m*j]*fr[it+j+nv/2];
              q=pi[m*j]*fi[it+j+nv/2];
              s=pr[m*j]+pi[m*j];
              s=s*(fr[it+j+nv/2]+fi[it+j+nv/2]);
              poddr=p-q; poddi=s-p-q;
              fr[it+j+nv/2]=fr[it+j]-poddr;
              fi[it+j+nv/2]=fi[it+j]-poddi;
              fr[it+j]=fr[it+j]+poddr;
              fi[it+j]=fi[it+j]+poddi;
            }
      }
    if (l!=0)
      for (i=0; i<=n-1; i++)
        { fr=fr/(1.0*n);
          fi=fi/(1.0*n);
        }
    if (il!=0)
      for (i=0; i<=n-1; i++)
        { pr=sqrt(fr*fr+fi*fi);
          pr=(pr/(n/2)); //各次谐波幅值,其中pr[1]为基波幅值
          if (fabs(fr)<0.000001*fabs(fi))//fabs()
            { if ((fi*fr)>0) pi=90.0;
              else pi=-90.0;
            }
          else
            pi=atan(fi/fr)*360.0/6.283185306;
        }
    return;
}
沙发
liudewei|  楼主 | 2008-12-15 10:16 | 只看该作者

固件库不是要5.0以上版本的IAR才能使用吗?

另外,用的万利的板子采用iar5.2的时候驱动似乎不能上,显示驱动出错

使用特权

评论回复
板凳
liudewei|  楼主 | 2008-12-15 10:41 | 只看该作者

谢谢netjob耐心的解答

但是现在需要在硬件上使用,现在就不知道应该怎样做了

使用特权

评论回复
地板
lixun00| | 2008-12-15 14:14 | 只看该作者

你这个还double,stm32那速度哪里受得了

使用特权

评论回复
5
liudewei|  楼主 | 2008-12-15 14:17 | 只看该作者

运行时间感觉很短的

运行时间感觉很短的,1024个点也就一秒钟多一点就可以了

使用特权

评论回复
6
幽游白书| | 2008-12-16 14:14 | 只看该作者

我是lz,不好意思,之前是个子函数,这个是我运行成功的程

#include "stdafx.h"
#include "math.h"

#define fftBufferSize 256
double fpr[fftBufferSize]={0};
double fpi[fftBufferSize]={0};
double ffr[fftBufferSize]={0}; 
double ffi[fftBufferSize]={0};
void kbfft(double *pr,double *pi,int n,int k,double *fr,double *fi,int l,int il);
int main(int argc, char* argv[])
{
    int i;
    
    for (i=0;i<=(fftBufferSize/2);i++)
  {
    fpr=(float)i/64.0;
    fpr[fftBufferSize-i]=(float)i/64.0;
  }
    kbfft(fpr,fpi,256,8,ffr,ffi,0,1);
    return 0;
}
    // 入口参数: 
// l: l = 0, 傅立叶变换; l = 1, 逆傅立叶变换
// il: il = 0,不计算傅立叶变换或逆变换模和幅角;il = 1,计算模和幅角
// n: 输入的点数,为偶数,一般为32,64,128,...,1024等
// k: 满足n=2^k(k>0),实质上k是n个采样数据可以分解为偶次幂和奇次幂的次数
// pr[]: l=0时,存放N点采样数据的实部
// l=1时, 存放傅立叶变换的N个实部
// pi[]: l=0时,存放N点采样数据的虚部 
// l=1时, 存放傅立叶变换的N个虚部
//
// 出口参数:
// fr[]: l=0, 返回傅立叶变换的实部
// l=1, 返回逆傅立叶变换的实部
// fi[]: l=0, 返回傅立叶变换的虚部
// l=1, 返回逆傅立叶变换的虚部
// pr[]: il = 1,l = 0 时,返回傅立叶变换的模
// il = 1,l = 1 时,返回逆傅立叶变换的模
// pi[]: il = 1,l = 0 时,返回傅立叶变换的辐角
// il = 1,l = 1 时,返回逆傅立叶变换的辐角
void kbfft(double *pr,double *pi,int n,int k,double *fr,double *fi,int l,int il)

    int it,m,is,i,j,nv,l0;
    double p,q,s,vr,vi,poddr,poddi;
    
    //排序
    for (it=0; it<=n-1; it++) 
      { m=it; is=0;
        for (i=0; i<=k-1; i++)
          { j=m/2; is=2*is+(m-2*j); m=j;
            fr[it]=pr[is]; fi[it]=pi[is];
          }
      }
    
    //蝶形运算
    pr[0]=1.0; pi[0]=0.0;
    p=6.283185306/(1.0*n);
    pr[1]=cos(p); pi[1]=-sin(p);
    if (l!=0) pi[1]=-pi[1];
    for (i=2; i<=n-1; i++)
      { p=pr[i-1]*pr[1]; q=pi[i-1]*pi[1];
        s=(pr[i-1]+pi[i-1])*(pr[1]+pi[1]);
        pr=p-q; pi=s-p-q;
      }
    for (it=0; it<=n-2; it=it+2)
      { vr=fr[it]; vi=fi[it];
        fr[it]=vr+fr[it+1]; fi[it]=vi+fi[it+1];
        fr[it+1]=vr-fr[it+1]; fi[it+1]=vi-fi[it+1];
      }
    m=n/2; nv=2;
    for (l0=k-2; l0>=0; l0--)
      { m=m/2; nv=2*nv;
        for (it=0; it<=(m-1)*nv; it=it+nv)
          for (j=0; j<=(nv/2)-1; j++)
            { p=pr[m*j]*fr[it+j+nv/2];
              q=pi[m*j]*fi[it+j+nv/2];
              s=pr[m*j]+pi[m*j];
              s=s*(fr[it+j+nv/2]+fi[it+j+nv/2]);
              poddr=p-q; poddi=s-p-q;
              fr[it+j+nv/2]=fr[it+j]-poddr;
              fi[it+j+nv/2]=fi[it+j]-poddi;
              fr[it+j]=fr[it+j]+poddr;
              fi[it+j]=fi[it+j]+poddi;
            }
      }
    if (l!=0)
      for (i=0; i<=n-1; i++)
        { fr=fr/(1.0*n);
          fi=fi/(1.0*n);
        }
    if (il!=0)
      for (i=0; i<=n-1; i++)
        { pr=sqrt(fr*fr+fi*fi);
          pr=(pr/(n/2)); //各次谐波幅值,其中pr[1]为基波幅值
          if (fabs(fr)<0.000001*fabs(fi))//fabs()
            { if ((fi*fr)>0) pi=90.0;
              else pi=-90.0;
            }
          else
            pi=atan(fi/fr)*360.0/6.283185306;
        }
    return;
}

使用特权

评论回复
7
幽游白书| | 2008-12-17 10:06 | 只看该作者

在vc上运行与在stm32上运行结果确实不一样

这个程序是网上找的,或者有高手能提供一个可用的fft程序么?谢谢大家

使用特权

评论回复
8
幽游白书| | 2008-12-30 17:23 | 只看该作者

后续的结果

很久没来,最后将程序实验了一下,确实是可行的,之前不能运行是因为我没有加一个头文件math.h,算出结果可能还是有误差,凑合着用下应该还行,大家有用过发现问题的可以指导一下^_^

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

27

主题

599

帖子

1

粉丝