txc012 发表于 2009-9-22 19:47:23

单片机fft和VC的fft计算结果不一样

恳请高手帮帮忙。
我用atmega16做32个点的fft。
在vc上算得的数据和单片机算的的数据部不全一样,只有一半是一样的,
已经非常仔细地校对过程序,定义的数据类型都一致,
恳请高手赐教,为何单片机和计算机的fft结果不一致

windy__xp 发表于 2009-9-22 19:57:48

程序贴出来,不然神仙都难帮你。

txc012 发表于 2009-9-22 20:29:58

/******************************************
//测试系统
//芯片:ATmega16L
//频率:8MHz内频
//电压:3.3V
//软件:ICCAVR
*******************************************/

#include "config.h"
#include "LCD.h"
#include "GUI.h"
#definePI264       
#defineN   64
//uintadcbuf; //信号实部(8位ad转换结果)
uint   fftbuf;
intwamp;
const charcostab={
                     127,126,125,122,117,112,105,98,
                   91,81,71,60,49,37,25,12,0,
                   -12,-25,-39,-49,-60,-71,-81,-90,
                   -98,-106,-112,-117,-122,-125,-126,-127,
                   -126,-126,-122,-117,-112, -106,-98,-90,
                   -81,-71,-60,-49,-37,-25,-12,0,
                  12,25,37,49,60,71,81,90,
                  98,106,112,117,122,125,126

                                                                             };
const char sintab={
                        0,12,25,37,49,60,71,81,
                                90,98,106,112,117,122,125,126,
                        127,126,125,122,117,112,106,98,
                        90,81,71,60,49,37,25,12,
                        0,-12,-25,-37,-49,-60,-71,-81,
                        -90,-98,-105,-112,-117,-122,-125,-126,
                        -127,-126,-125,-122,-117,-112,-106,-98,
                          -90,-81,-71,-60,-49,-39,-25,-12
                                                };
uint adcbuf={
                     4,5,34,7,67,1,6,13,
                        45,54,67,7,34,81,1,123,
                     15,5,5,87,31,1,61,13,
                      45,4,4,8,23,81,6,3,
                     4,5,34,7,67,1,6,13,
                      45,54,67,7,34,81,1,123,
                15,5,5,87,31,1,61,13,
                   45,4,4,8,23,81,6,3
                               
                                                              };
                                                               
uintsqrt2(uintdata)//开方
{
uints=0,i;
for(i=0x80;i>0;i>>=1)
{
s|=i;
if(s*s>data)
   s&=~i;
}
return (uint)s;
}


/****************************************************
x:输入数据实部,输出数据实部(有符号数)
y:输入数据虚部,输出数据虚部(有符号数)
n:点数
*************************************************/
//void fft(int x[],int y[],int n,uchar sign)
void fft(int x[],inty[],ucharn)
{//x[]为实部,y[]为虚部(全为0),n为点数
inttr=0;int ti=0;int p=0;int q=0;
uchar i=0;uchar j=0;uchar k=0;uchar qn=0;uchar a=0;
uchar b=0;uchar c=0;uchar cen=0;uchar zu=0;uchar ge=0;

a=n-1;

for(i=0,j=0;i<a;i++)//循环n-1次
{                                                                                          
if(i<j)                                                                       
{
   tr=x;
   x=x;
   x=tr;
   ti=y;
   y=y;
   y=ti;
}//交换x<->x,y<->y
k=n/2;
while(k<(j+1))
{
   j=j-k;
   k=k/2;
}
j=j+k;
}//此循环把原序列变成2点奇偶序列

/****************************************/
for(i=1,j=1;i<8;i++)
{
   j=2*j;//j=2^p
   if(j>=n)break;
}
//2的i次方=n
cen=i;                                             //如果n=8,则cen=3;
zu=n;
for(i=0;i<cen;i++)                   //层数(0,1,2)
{
zu=zu/2;                           //组数(4,2,1)
for(j=0;j<zu;j++)                   //第i 层中的第 j组
{
   ge=(n/zu)/2;            //一组中蝶形的个数(1,2,4)      
   for(k=0;k<ge;k++)           //第 j 组中的第k个
   {                                           //第 a 和第 b 个元素作蝶形运算,WNC
    a=j*ge*2+k;                           //(0,2,4,6)(0,1,4,5)(0,1,2,3)
    b=a+ge;                                   //(ge=1,2,4)
    c=k*zu;                                   //(0,0,0,0)(0,2,0,2)(0,1,2,3)
        qn=(PI2/n)*c;
        //注意sign
        tr=(x*costab+y*sintab)>>7;//由于正余弦表放大128倍,此处缩小128倍
    ti=(y*costab-x*sintab)>>7;
    p=x;
    q=y;
        //蝶形运算
    x=(p+tr)>>1;//防止数据溢出
   y=(q+ti)>>1;
   x=(p-tr)>>1;
   y=(q-ti)>>1;
   }
}
}
}

void getamp(intx[],int y[],intwamp[],uintlen)//这里显示虚部+100后的值,与VC上的值只有一半是一样的
{
        int i;
       
        //for(i=0;i<len;i++)
        //{
                //wamp=sqrt2(x*x+y*y)<<2;//开方后放大
               
        //}
   
   for(i=0;i<len;i++)
   {
            disdata(1+i*16,40,y+100,0);
                     if(i>14&&i<30)
                {   
                            for(i=15;i<30;i++)
                                           {
                                                  disdata(1+(i-15)*16,90,y+100,0);
                                                   }
                                }
                       if(i>29&&i<len)
                               {                                  
                                                 for(i=30;i<len;i++)
                                                  {
                                                  disdata(1+(i-30)*16,140,y+100,0);
                                                   }
                        }
                                  
}
       
       
       
   GUI_HLine(20, 98, 236, 0);      //画竖线
   GUI_HLine(20, 48, 236, 0);
}

//主程序
void main()
{   uchar i;
      LCD_Init();   //LCD初始化
      GUI_ClearSCR(Black);            //清屏
      for(i=0;i<N;i++)
          {
       
           fftbuf=0;                        //清信号虚部
          }
          
          // disdata(1,140,adcbuf,0);
        //disdata(25,140,fftbuf,0);
             fft((int*)adcbuf,(int*)fftbuf,N);                            //fft 变换
       
          getamp((int*)adcbuf,(int*)fftbuf,(int*)fftbuf,N/2); //求模
       
          
          
}

Muuvyd 发表于 2009-9-22 22:10:13

单片机int是16bit pc是32bit的

sharpufo 发表于 2009-9-22 22:14:20

单片机int是16 bit

txc012 发表于 2009-9-23 09:47:52

我把单片机的int型换成long行,unsigned int型换成unsigned long,结果还是不行啊,求高手帮助

txc012 发表于 2009-9-23 10:05:33

结果一致了,单片机的int型是16位的,char型是8位的,计算机的int型是32位的,char型是16位的

ShangGuan 发表于 2009-9-28 13:48:07

/****************************************************
x:输入数据实部,输出数据实部(有符号数)
y:输入数据虚部,输出数据虚部(有符号数)
n:点数
*************************************************/
//void fft(int x[],int y[],int n,uchar sign)
void fft(int x[],inty[],ucharn)
{//x[]为实部,y[]为虚部(全为0),n为点数
inttr=0;int ti=0;int p=0;int q=0;
uchar i=0;uchar j=0;uchar k=0;uchar qn=0;uchar a=0;
uchar b=0;uchar c=0;uchar cen=0;uchar zu=0;uchar ge=0;

a=n-1;

for(i=0,j=0;i<a;i++)//循环n-1次
{   
if(i<j)   
{
   tr=x;
   x=x;
   x=tr;
   ti=y;
   y=y;
   y=ti;
}//交换x<->x,y<->y
k=n/2;
while(k<(j+1))
{
   j=j-k;
   k=k/2;
}
j=j+k;
}//此循环把原序列变成2点奇偶序列

/****************************************/
for(i=1,j=1;i<8;i++)
{
   j=2*j;//j=2^p
   if(j>=n)break;
}
//2的i次方=n
cen=i;          //如果n=8,则cen=3;
zu=n;
for(i=0;i<cen;i++)    //层数(0,1,2)
{
zu=zu/2;            //组数(4,2,1)
for(j=0;j<zu;j++)    //第i 层中的第 j组
{   
   ge=(n/zu)/2;            //一组中蝶形的个数(1,2,4)      
   for(k=0;k<ge;k++)    //第 j 组中的第k个
   {    //第 a 和第 b 个元素作蝶形运算,WNC
    a=j*ge*2+k;    //(0,2,4,6)(0,1,4,5)(0,1,2,3)
    b=a+ge;    //(ge=1,2,4)
    c=k*zu;    //(0,0,0,0)(0,2,0,2)(0,1,2,3)
qn=(PI2/n)*c;
//注意sign



    tr=(x*costab+y*sintab)>>7; //这里为什么是+?
    ti=(y*costab-x*sintab)>>7; //这么为什么是-?


      (tr+ I*ti)=(x+I*y) * (cos(q)+ I*sin(q));
         实部是tr:x*cos(q) - y*sin(q);
         虚部是ti:x*sin(q) + y*cos(q);
         ????????????????????????????????????

    p=x;
    q=y;
//蝶形运算
    x=(p+tr)>>1;//防止数据溢出
   y=(q+ti)>>1;
   x=(p-tr)>>1;
   y=(q-ti)>>1;
   }
}
}
}

ShangGuan 发表于 2009-9-30 17:31:21

明白了。

FFT 旋转角度是负方向,而正弦表里面的值是正方向。

XYXZ1010 发表于 2010-1-30 21:23:12

不太明白这个qn=(PI2/n)*c;,PI2 = 64,n = 64,那不是qn=(64/64)*c?

astankvai 发表于 2010-11-1 14:06:37

VC的char是16位的?我仿真的时候怎么是8位的?

taotaoliu 发表于 2010-11-1 14:11:48

果然是因为位数的问题,
用单片机做傅立叶变换,高手呀,呵呵

sunmy 发表于 2010-11-1 14:12:59

有用就mark!

hemjidn 发表于 2010-11-1 18:19:18

VC的char肯定是8位的……wchar才是16位的TCHAR根据编译选项或UNICODE宏决定是8位或16位

cuikai12345 发表于 2010-11-1 19:55:13

mark

fanwt 发表于 2010-11-1 22:18:25

mark

rlogin 发表于 2010-11-2 00:39:29

~

hsztc 发表于 2010-11-2 01:51:54

mark

myfriend6042 发表于 2010-11-22 16:20:47

mark

gloryzkl 发表于 2011-3-13 14:09:02

mark

xk2yx 发表于 2011-3-13 14:20:16

mark

longfeixue 发表于 2011-3-23 16:54:50

mark

Hello_World 发表于 2011-3-23 19:04:33

mark

cain.lee 发表于 2011-3-23 20:59:37

主要是乘法器的问题吧··一个是8位的一个是32位的···以前做算法也遇到过··只不过单片机FFT够呛啊···

alta 发表于 2012-7-25 17:18:10

留着用到的时候

shh_hqss 发表于 2012-11-16 16:07:55

mark,用得着

junwugui 发表于 2013-4-13 15:50:02

最近也在用Atmega16做FFT运算
页: [1]
查看完整版本: 单片机fft和VC的fft计算结果不一样