/*******************************************************************************
//名称:定点FFT算法程序
//人员:
//日期:
//说明:MEGA128L,16MHZ,IAR420A
//占用周期数:input(5677) Execute(160864) Output(16659)
//16MHZ时ms 0.3548 10.054 1.0412
//fft_r输入信号,范围-255到+255之间,即带符号位9位数据。不在此范围则结果错误。
//输出
*******************************************************************************/
#include "iom128.h"
#include "intrinsics.h"
#include "math.h"
#define INT8 signed char
#define INT16 signed int
#define INT32 signed long
#define UINT8 unsigned char
#define UINT16 unsigned int
#define UINT32 unsigned long
/******************************************************************************/
#define FFT_N 128 ; //本程序是128点FFT变换
INT16 fft_r[128]={ //实数采样点,共128点。
//单周期方波
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,
-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,
-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,
-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255
//4周期方波
// 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
//-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,
// 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
//-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,
// 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
//-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,
// 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
//-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255
//直流恒量
//0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,
//0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,
//0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,
//0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,
//0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,
//0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,
//0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,
//0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff,0x0ff
};
INT16 fft_temp[128]; //采样点虚部,共128点。
/******************************************************************************/
__flash UINT16 fft_window[128]={ //汉宁窗
2621, 2639, 2693, 2784, 2910, 3073, 3270, 3502,
3768, 4068, 4401, 4765, 5161, 5587, 6042, 6525,
7036, 7571, 8132, 8715, 9320, 9945, 10588, 11249,
11926, 12616, 13318, 14031, 14753, 15482, 16216, 16954,
17694, 18433, 19171, 19905, 20634, 21356, 22069, 22772,
23462, 24138, 24799, 25443, 26068, 26673, 27256, 27816,
28352, 28862, 29345, 29800, 30226, 30622, 30987, 31319,
31619, 31885, 32117, 32315, 32477, 32603, 32694, 32748,
32766, 32748, 32694, 32603, 32477, 32315, 32117, 31885,
31619, 31319, 30987, 30622, 30226, 29800, 29345, 28862,
28352, 27816, 27256, 26673, 26068, 25443, 24799, 24138,
23462, 22772, 22069, 21356, 20634, 19905, 19171, 18433,
17694, 16954, 16216, 15482, 14753, 14031, 13318, 12616,
11926, 11249, 10588, 9945, 9320, 8715, 8132, 7571,
7036, 6526, 6042, 5587, 5161, 4765, 4401, 4068,
3768, 3502, 3270, 3073, 2910, 2784, 2693, 2639
};
__flash UINT8 fft_reverse[128]={ //倒位序表
0, 64,32,96, 16,80,48,112,8, 72,40,104,24,88,56,120,
4, 68,36,100,20,84,52,116,12,76,44,108,28,92,60,124,
2, 66,34,98, 18,82,50,114,10,74,42,106,26,90,58,122,
6, 70,38,102,22,86,54,118,14,78,46,110,30,94,62,126,
1, 65,33,97, 17,81,49,113,9, 73,41,105,25,89,57,121,
5, 69,37,101,21,85,53,117,13,77,45,109,29,93,61,125,
3, 67,35,99, 19,83,51,115,11,75,43,107,27,91,59,123,
7, 71,39,103,23,87,55,119,15,79,47,111,31,95,63,127
};
__flash INT16 fft_wrcos[64]={ //旋转因子实部
32767, 32728, 32609, 32412, 32137, 31785, 31356, 30852,
30273, 29621, 28898, 28105, 27245, 26319, 25329, 24279,
23170, 22005, 20787, 19519, 18204, 16846, 15446, 14010,
12539, 11039, 9512, 7962, 6393, 4808, 3212, 1608,
0, -1608, -3212, -4808, -6393, -7962, -9512, -11039,
-12539,-14010,-15446,-16846,-18204,-19519,-20787,-22005,
-23170,-24279,-25329,-26319,-27245,-28105,-28898,-29621,
-30273,-30852,-31356,-31785,-32137,-32412,-32609,-32728
};
__flash INT16 ttt_wisin[64]={ //旋转因子虚部
0, 1608, 3212, 4808, 6393, 7962, 9512, 11039,
12539, 14010, 15446, 16846, 18204, 19519, 20787, 22005,
23170, 24279, 25329, 26319, 27245, 28105, 28898, 29621,
30273, 30852, 31356, 31785, 32137, 32412, 32609, 32728,
32767, 32728, 32609, 32412, 32137, 31785, 31356, 30852,
30273, 29621, 28898, 28105, 27245, 26319, 25329, 24279,
23170, 22005, 20787, 19519, 18204, 16846, 15446, 14010,
12539, 11039, 9512, 7962, 6393, 4808, 3212, 1608
};
/******************************************************************************/
void fft_real( void ); //fft变换函数
UINT16 sqrt_16( UINT32 M ); //开平方函数
extern UINT32 fft_muls16( INT16 mula, INT16 mulb ); //16x16位乘法运算函数
volatile UINT16 f[42],ff; //存放结果
/******************************************************************************/
void main( void )
{
while(1){
fft_real( ); //fft变换函数
while(1); //变换后结果取代原来数据,所以仅能运行1次
}
}
/******************************************************************************/
//名称: fft_real() 定点数快速傅立叶变换函数
//参数: 无入口和出口参数
//说明: 计算42次谐波
/******************************************************************************/
void fft_real( void )
{
UINT8 i,j,k;
UINT8 l,b,p;
UINT8 m;
INT16 tr,ti;
INT16 rcos_isin,rsin_icos;
INT16 *pa,*pc;
pa= fft_r;
pc= fft_temp;
for(i=0; i<128; i++)
{
*pc = *pa; //不加窗
//*pc = ((INT32)(*pa)*(fft_window))>>15; //((UINT32)(*pa)*(*pb))>>15; //加窗
pa++; pc++;
}
pa= fft_r;
pc= fft_temp;
for(i=0; i<128; i++)
{
pa = pc[fft_reverse]; //倒位序
pc[fft_reverse] = 0; //虚部为0
}
b= 1; //b=2^l =1 ,2 ,4 ,8,16,32,64
i= 6; //p=2^(6-l)=64(6),32(5),16(4),8(3),4(2),2(1),1(0)
for(l=0; l<7; l++) //级数
{
for(j=0; j<b; j++) //旋转因子指数
{
p= (j<<i); //p=2^(6-l)=64(6),32(5),16(4),8(3),4(2),2(1),1(0)
for(k=j; k<128; ) //蝶形
{
m = k+b;
tr=fft_r[k];
ti=fft_temp[k];
//表中值最大为32768, 32768/(2^15)=1.
rcos_isin= ((INT32)fft_r[m]* fft_wrcos[p]+(INT32)fft_temp[m]* ttt_wisin[p])>>15;
rsin_icos= ((INT32)fft_r[m]* ttt_wisin[p]-(INT32)fft_temp[m]* fft_wrcos[p])>>15;
//rcos_isin= (fft_muls16(fft_r[m], fft_wrcos[p]) + fft_muls16(fft_temp[m], ttt_wisin[p]))>>15;
//rsin_icos= (fft_muls16(fft_r[m], ttt_wisin[p]) + fft_muls16(fft_temp[m], fft_wrcos[p]))>>15;
fft_r[k] =(tr+ rcos_isin); //为了保证TR,TI不溢出,输入信号位数9位。
fft_temp[k] =(ti- rsin_icos);
fft_r[m] =(tr- rcos_isin);
fft_temp[m] =(ti+ rsin_icos);
k = m+b; //k=k+2*b
} //for k
} //for j
i--; //p=2^(6-l)=64,32,16,8,4 ,2 ,1
b<<=1; //b=2^l =1 ,2 ,4 ,8,16,32,64
} //for l
for(i=0; i<42; i++) //求得的谐波频率幂次小于点数的1/3。
{
f= sqrt_16((INT32)((INT32)fft_r*fft_r+ (INT32)fft_temp*fft_temp) );
// f= sqrt_16( fft_muls16(fft_r, fft_r) + fft_muls16(fft_temp, fft_temp) );
}
ff=f[0]; //f[4]=20774; f[12]=7010; f[20]=4318; f[28]=3208; f[36]=2635;
//直流量 基波 3次 5次 7次 9次
}
/******************************************************************************/
//名称:sqrt_16()
//参数:M入口参数32位,N出口参数16位
//说明:开平方函数
/******************************************************************************/
UINT16 sqrt_16( UINT32 M )
{
UINT16 N, i;
UINT32 tmp, ttp; // 结果、循环计数
if(M == 0) // 被开方数,开方结果也为0
return 0;
N = 0;
tmp = (M >> 30); // 获取最高位:B[m-1]
M <<= 2;
if(tmp > 1) // 最高位为1
{
N ++; // 结果当前位为1,否则为默认的0
tmp -= N;
}
for(i=15; i>0; i--) // 求剩余的15位
{
N <<= 1; // 左移一位
tmp <<= 2;
tmp += (M >> 30); // 假设
ttp = N;
ttp = (ttp<<1)+1;
M <<= 2;
if (tmp >= ttp) // 假设成立
{
tmp -= ttp;
N ++;
}
}
return N;
}
/******************************************************************************/ |