|
楼主 |
发表于 2009-9-22 20:29:58
|
显示全部楼层
/******************************************
//测试系统
//芯片:ATmega16L
//频率:8MHz内频
//电压:3.3V
//软件:ICCAVR
*******************************************/
#include "config.h"
#include "LCD.h"
#include "GUI.h"
#define PI2 64
#define N 64
//uint adcbuf[N]; //信号实部(8位ad转换结果)
uint fftbuf[N];
int wamp[N];
const char costab[PI2]={
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[PI2]={
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[N]={
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
};
uint sqrt2(uint data)//开方
{
uint s=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[],int y[],uchar n)
{//x[]为实部,y[]为虚部(全为0),n为点数
int tr=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[j];
x[j]=x;
x=tr;
ti=y[j];
y[j]=y;
y=ti;
}//交换x<->x[j],y<->y[j]
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[qn]+y*sintab[qn])>>7;//由于正余弦表放大128倍,此处缩小128倍
ti=(y*costab[qn]-x*sintab[qn])>>7;
p=x[a];
q=y[a];
//蝶形运算
x[a]=(p+tr)>>1;//防止数据溢出
y[a]=(q+ti)>>1;
x=(p-tr)>>1;
y=(q-ti)>>1;
}
}
}
}
void getamp(int x[],int y[],int wamp[],uint len)//这里显示虚部+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[1],0);
// disdata(25,140,fftbuf[1],0);
fft((int*)adcbuf,(int*)fftbuf,N); //fft 变换
getamp((int*)adcbuf,(int*)fftbuf,(int*)fftbuf,N/2); //求模
} |
|