📄 fft_new_test.lst
字号:
224 03.名称:BitReverse
225 入口:BR_Array[]:
226 -操作的对象数组。
227 出口:无
228 功能:对经过为反向的地址重新排序
229 数组BRTable[]被用来查找哪个值要被交换,只有一半的值被存储在数组中,另一半通过镜像前一半
230 得到。
231 =================================================================================================*/
232 void BitReverse(int BR_Array[])
233 {
234 1 #if(NUM_FFT>=512)
unsigned int swapA,swapB,sw_cnt;
C51 COMPILER V7.50 FFT_NEW_TEST 07/26/2007 09:57:47 PAGE 5
#endif
237 1
238 1 #if(NUM_FFT<=256)
239 1 unsigned char swapA,swapB,sw_cnt;
240 1 #endif
241 1
242 1 int TempStore;
243 1 for(sw_cnt=1;sw_cnt<NUM_FFT/2;sw_cnt++)//第一部分的交换
244 1 {
245 2 swapA=sw_cnt; //保存当前位置
246 2 swapB=BRTable[sw_cnt]*2; //找到位反向索引
247 2 if(swapB>swapA) //如果位反向索引值比当前值大则交换
248 2 {
249 3 TempStore=BR_Array[swapA];
250 3 BR_Array[swapA]=BR_Array[swapB];
251 3 BR_Array[swapB]=TempStore;
252 3 }
253 2 swapA+=NUM_FFT/2; //第二部分的交换
254 2 swapB++;
255 2 if (swapB>swapA)
256 2 {
257 3 TempStore=BR_Array[swapA];
258 3 BR_Array[swapA]=BR_Array[swapB];
259 3 BR_Array[swapB]=TempStore;
260 3 }
261 2 }
262 1 }
263 /*=================================================================================================
264 04.名称:IntFFT
265 入口:ReArray[]:
266 ImArray[]:
267 出口:无
268 功能:FFT函数,对输入数组ReArray[]执行时间抽取的基2的FFT算法。在FFT算法的每一步,都要执行蝶形
269 方程:
270
271 Re1=Re1+(Cos(x)*Re2+Sin(x)*Im2)
272 Re2=Re1-(Cos(x)*Re2+Sin(x)*Im2)
273 Im1=Im1+(Cos(x)*Im2-Sin(x)*Re2)
274 Im2=Im1-(Cos(x)*Im2-Sin(x)*Re2)
275
276 程序使用如下值计算上式:
277
278 Re1=ReArray[indexA],Re2=ReArray[indexB]
279 Im1=ImArray[indexA],Im2=ImArray[indexB]
280
281 x =角度: 2*pi*(sin_index/NUM_FFT)单位:弧度;存储在代码空间SinTable[]数组中
282
283 关键点:
284 1. 实部的数据在ReArray[]数组中,2的幂,以16-bit二进制格式存放,虚部假设全为0
285 存放在ImArray[]数组中。
286 2. 实部假设被以位反向格式存储。
287 3. 正弦和余弦值被事先计算好存放在表中,事实上,表中只保存了1/4周期的正弦值。
288 4. 为了优化代码,只用整形数计算(没有浮点操作),这样可以节省存储空间。FFT所
289 有的中间计算结果都以16-bit形式存储,故程序的精度有限。当输入数据少于16-bit
290 时,数据左对齐在执行FFT可产生最好的计算结果。
291 5. FFT的算法为基-2算法,所以,采样点的个数必须为2^N,N为整数。最少的采样点个数
292 为4,常数NUM_FFT定义了采样点的个数。
293 6. 对输入数据进行优化,只有实部输入,虚部全部设置为0。在这一步中,删除了不必要
294 的重复部分,对于角度0这一点的计算,所有的sin值都时0,所有的cos值都是1。另外
295 由于虚部为0,故计算时的值也都为等于0。
296 =================================================================================================*/
297 void IntFFT(int ReArray[],int ImArray[])
C51 COMPILER V7.50 FFT_NEW_TEST 07/26/2007 09:57:47 PAGE 6
298 {
299 1 #if(NUM_FFT>=512)
unsigned int sin_index,g_cnt,s_cnt; // Keeps track of the proper index
unsigned int indexA,indexB; // locations for each calculation
#endif
303 1
304 1 #if(NUM_FFT<=256)
305 1 unsigned char sin_index,g_cnt,s_cnt; // Keeps track of the proper index
306 1 unsigned char indexA,indexB; // locations for each calculation
307 1 #endif
308 1
309 1 unsigned int group=NUM_FFT/4,stage=2;
310 1 long CosVal,SinVal;
311 1 long TempImA,TempImB,TempReA,TempReB,TempReA2,TempReB2;
312 1 IBALONG ReTwid,ImTwid,TempL;
313 1
314 1 indexA=0;
315 1 for(g_cnt=0;g_cnt<NUM_FFT/2;g_cnt++)
316 1 {
317 2 indexB=indexA+1;
318 2 TempReA=ReArray[indexA];
319 2 TempReB=ReArray[indexB];
320 2
321 2 TempL.l=(long)TempReA+TempReB; //计算新的ReArray[indexA]的值
322 2 if((TempL.l<0)&&(0x01&TempL.b[3])) TempReA2=(TempL.l>>1)+1;
323 2 else TempReA2=TempL.l>>1;
324 2
325 2 TempL.l=(long)TempReA-TempReB; //计算新的ReArray[indexB]的值
326 2 if((TempL.l<0)&&(0x01&TempL.b[3])) ReArray[indexB]=(TempL.l>>1)+1;
327 2 else ReArray[indexB]=TempL.l>>1;
328 2
329 2 ReArray[indexA]=TempReA2;
330 2 ImArray[indexA]=0; //将虚部设置为0
331 2 ImArray[indexB]=0;
332 2 indexA=indexB+1;
333 2 }
334 1 while(stage<=NUM_FFT/2)
335 1 {
336 2 indexA=0;
337 2 sin_index=0;
338 2 for(g_cnt=0;g_cnt<group;g_cnt++)
339 2 {
340 3 for(s_cnt=0;s_cnt<stage;s_cnt++)
341 3 {
342 4 indexB=indexA+stage;
343 4
344 4 TempReA=ReArray[indexA];
345 4 TempReB=ReArray[indexB];
346 4 TempImA=ImArray[indexA];
347 4 TempImB=ImArray[indexB];
348 4
349 4 if(sin_index==0) //"x"=0弧度
350 4 {
351 5 TempL.l=(long)TempReA+TempReB;//计算新的ReArray[indexA]的值
352 5 if((TempL.l<0)&&(0x01&TempL.b[3])) TempReA2=(TempL.l>>1)+1;
353 5 else TempReA2=TempL.l>>1;
354 5
355 5 TempL.l=(long)TempReA-TempReB;//计算新的ReArray[indexB]的值
356 5 if((TempL.l<0)&&(0x01&TempL.b[3])) TempReB2=(TempL.l>>1)+1;
357 5 else TempReB2=TempL.l>>1;
358 5
359 5 TempL.l=(long)TempImA-TempImB;//计算新的ImArray[indexB]的值
C51 COMPILER V7.50 FFT_NEW_TEST 07/26/2007 09:57:47 PAGE 7
360 5 if((TempL.l<0)&&(0x01&TempL.b[3])) TempImB=(TempL.l>>1)+1;
361 5 else TempImB=TempL.l>>1;
362 5
363 5 TempL.l=(long)TempImA+TempImB;//计算新的ImArray[indexA]的值
364 5 if((TempL.l<0)&&(0x01&TempL.b[3])) TempImA=(TempL.l>>1)+1;
365 5 else TempImA=TempL.l>>1;
366 5 }
367 4 else if(sin_index==NUM_FFT/4) //"x"=pi/2弧度
368 4 {
369 5 TempL.l=(long)TempReA-TempImB;//计算新的ReArray[indexB]的值
370 5 if((TempL.l<0)&&(0x01&TempL.b[3])) TempReB2=(TempL.l>>1)+1;
371 5 else TempReB2=TempL.l>>1;
372 5
373 5 TempL.l=(long)TempReA+TempImB;//计算新的ReArray[indexA]的值
374 5 if((TempL.l<0)&&(0x01&TempL.b[3])) TempReA2=(TempL.l>>1)+1;
375 5 else TempReA2=TempL.l>>1;
376 5
377 5 TempL.l=(long)TempImA+TempReB;//计算新的ImArray[indexB]的值
378 5 if((TempL.l<0)&&(0x01&TempL.b[3])) TempImB=(TempL.l>>1)+1;
379 5 else TempImB=TempL.l>>1;
380 5
381 5 TempL.l=(long)TempImA-TempReB;//计算新的ImArray[indexA]的值
382 5 if((TempL.l<0)&&(0x01&TempL.b[3])) TempImA=(TempL.l>>1)+1;
383 5 else TempImA=TempL.l>>1;
384 5 }
385 4 else
386 4 {
387 5 if(sin_index>NUM_FFT/4) //如果没有上述情况,蝶形运算中的sin和cos值将通过查表得到。
388 5 {
389 6 SinVal=SinTable[(NUM_FFT/2)-sin_index];
390 6 CosVal=-SinTable[sin_index -(NUM_FFT/4)];
391 6 }
392 5 else
393 5 {
394 6 SinVal=SinTable[sin_index];
395 6 CosVal=SinTable[(NUM_FFT/4)-sin_index];
396 6 } //蝶形运算方程通过sin值和cos值来计算
397 5 ReTwid.l=((long)TempReB*CosVal)+((long)TempImB*SinVal);
398 5 ImTwid.l=((long)TempImB*CosVal)-((long)TempReB*SinVal);
399 5
400 5 TempL.i[1]=0; //计算新的ReArray[indexA]的值
401 5 TempL.i[0]=TempReA;
402 5 TempL.l=TempL.l>>1;
403 5 ReTwid.l+=TempL.l;
404 5 if((ReTwid.l<0)&&(ReTwid.i[1])) TempReA2=ReTwid.i[0]+1;
405 5 else TempReA2=ReTwid.i[0];
406 5
407 5 TempL.l=TempL.l<<1; //计算新的ReArray[indexB]的值
408 5 TempL.l-=ReTwid.l;
409 5 if((TempL.l<0)&&(TempL.i[1])) TempReB2=TempL.i[0]+1;
410 5 else TempReB2=TempL.i[0];
411 5
412 5 TempL.i[1]=0; //计算新的ImArray[indexA]的值
413 5 TempL.i[0]=TempImA;
414 5 TempL.l=TempL.l>>1;
415 5 ImTwid.l+=TempL.l;
416 5 if((ImTwid.l<0)&&(ImTwid.i[1])) TempImA=ImTwid.i[0]+1;
417 5 else TempImA=ImTwid.i[0];
418 5
419 5 TempL.l= TempL.l<<1; //计算新的ImArray[indexB]的值
420 5 TempL.l-=ImTwid.l;
421 5 if((TempL.l<0)&&(TempL.i[1])) TempImB=TempL.i[0]+1;
C51 COMPILER V7.50 FFT_NEW_TEST 07/26/2007 09:57:47 PAGE 8
422 5 else TempImB=TempL.i[0];
423 5 }
424 4 ReArray[indexA]=TempReA2;
425 4 ReArray[indexB]=TempReB2;
426 4 ImArray[indexA]=TempImA;
427 4 ImArray[indexB]=TempImB;
428 4 indexA++;
429 4 sin_index+=group;
430 4 }
431 3 indexA=indexB+1;
432 3 sin_index=0;
433 3 }
434 2 group/=2;
435 2 stage*=2;
436 2 }
437 1 }
438 /*=================================================================================================
439 12.名称:ADC0_ISR
440 入口:无
441 出口:无
442 功能:ADC0中断服务子程序
443 =================================================================================================*/
444 void ADC0_ISR(void) interrupt 15 using 3
445 {
446 1 ADCINT=0; //清ADC转换标志位
447 1 Real[ADC_Index]=ADC0; //存ADC的转换值
448 1 ADC_Index++; //采样次数加1
449 1 if (ADC_Index>=NUM_FFT) //达到采样数
450 1 {
451 2 Conversion_Set_Complete=1; //标志主程序
452 2 EIE2&=~0x02; //ADC中断禁能
453 2 }
454 1 }
455 /*-----------------------------------------------------------------------------------------------*/
456 //FFT_New_Test.c
C51 COMPILATION COMPLETE. 0 WARNING(S), 6 ERROR(S)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -