?? fft_new_test.c
字號:
/*-------------------------------------------------------------------------------------------------
文件名稱:FFT_New_Test.c
創建日期:07.06.12
修改日期:07.06.18
-整理
文件說明:功能:
-基于C8051F000系列單片機的FFT試驗程序
參數:
-通道0的IDT:0x00000100
-通道0的MSK:0x1FFFFFFF(通道0只能接受IDT為0x00000100的消息)
-通道1的IDT:0x00000101
-通道1的MSK:0x1FFFFFFF(通道1只能發送IDT為0x00000101的消息)
-UartBuffer大小為16字節
-CanBuffer 大小為16字節
創建人: 李大偉
-------------------------------------------------------------------------------------------------*/
#include <stdio.h>
#include "C8051F000.h"
#include "FFT_Code_Tables.h"
//ADC0寄存器定義
sfr16 ADC0 = 0xBE;
//數據的位數
#define NUM_BITS 16
//外部XRAM數據的起始
#define DATA_BEGIN 0x0000
//外部時鐘頻率,PLL輸出頻率=(EXTCLK*9/4)(Hz)
#define EXTCLK 22118400
#define SYSCLK 49760000
//UART0波特率
#define BAUDRATE 115200
//采樣頻率(Hz)
#define SAMPLE_RATE 10000
//為:1,只運行一次
#define RUN_ONCE 1
typedef union IBALONG
{
long l;
unsigned int i[2];
unsigned char b[4];
}IBALONG;
typedef union BAINT
{
int i;
unsigned char b[2];
}BAINT;
//函數申明
void WindowCalc(int Win_Array[], unsigned char SE_data);
void IntFFT(int ReArray[], int ImArray[]);
void BitReverse(int BR_Array[]);
void ADC0_ISR (void);
//全局變量
//FFT的XRAM空間=NUM_FFT*4字節(起始于DATA_BEGIN)
int xdata Real[NUM_FFT] _at_ DATA_BEGIN;
int xdata Imag[NUM_FFT] _at_ (DATA_BEGIN+(NUM_FFT*2));
//NUM_FFT的定義在"FFT_Code_Tables.h"頭文件中
#if(NUM_FFT>=256)
unsigned int index,ADC_Index;
#endif
#if(NUM_FFT<256)
unsigned char index,ADC_Index;
#endif
unsigned int BinNum; //循環變量
bit Conversion_Set_Complete;//一輪采樣結束標志位
/*=================================================================================================
01.名稱:main
入口:無
出口:無
功能:系統主函數
=================================================================================================*/
void main()
{
WDTCN = 0xDE; //看門狗
WDTCN = 0xAD;
OSCICN = 0x07; //時鐘
XBR0 = 0x04; //I/O
XBR2 = 0x40;
REF0CN = 0x03; //參考電壓
CKCON = 0x10; //定時器
TCON = 0x40;
TMOD = 0x20;
TH1 = 0xCC;
TMR3CN = 0x06;
TMR3RLL = 0x40;
TMR3RLH = 0x01;
TMR3L = 0x40;
TMR3H = 0x01;
SCON = 0x40; //UART
ADC0CF = 0x80; //ADC
ADC0CN = 0x85;
IE = 0x80; //中斷使能
while(1)
{
DisOfRuler1=SingleFrqMeasure(1);
DisOfRuler2=SingleFrqMeasure(2);
DisOfRuler3=SingleFrqMeasure(3);
}
}
/*=================================================================================================
01.名 稱:SingleFrqMeasure()
功 能:單尺測量過程
參 數:Sel: 0 - 關閉
1 - 5.9348MHz
2 - 593.48KHz
3 - 59.348KHz
返 回:對應尺的距離值
=================================================================================================*/
float SingleFrqMeasure(unsigned char SelFrq)
{
float PhaseW,PhaseN;
//光強檢測GetSignalRange();
//SelFrq控制CPLD選擇相應的頻率測距
PhaseW=GetPhase(OUT);
PhaseN=GetPhase(IN);
//將角度值轉化為距離值
switch(Sel)
{
case 0x01://5.9348MHz
break;
case 0x02://593.48KHz
break;
case 0x03://59.348KHz
break;
case 0x00://00
break;
default:
break;
}
//距離:
return (PhaseW-PhaseN);
}
/*=================================================================================================
01.名 稱:GetPhase()
功 能:計算距離值
參 數:無
返 回:無
=================================================================================================*/
float GetPhase(unsigned char NW)
{
float angle;
//NW控制電機打到內或者外光路
ADC_Index=0;
Conversion_Set_Complete=0;
EIE2|=0x02; //ADC中斷允許
while(!Conversion_Set_Complete);
//對Real數據進行排序
Sort(Real);
WindowCalc(Real,1); //加窗
BitReverse(Real); //將輸入的數據位反向重排
IntFFT(Real,Imag); //對輸入的數據進行FFT運算
angle=atan(Imag[1]/Real[1]);
return ((180/pi)*angle); //轉成距離值
}
/*=================================================================================================
02.名稱:WindowCalc
入口:
-Win_Array[]:為0到(NUM_FFT/2)-1的采樣數據所對應窗口系數,對于NUM_FFT/2到NUM_FFT-1的采樣數據
所對應窗口系數可通過0到(NUM_FFT/2)-1的采樣數據所對應窗口系數鏡像得到。窗口值為
一個小于1的值(WindowFunc[x]/65536),NUM_FFT/2處的值假設為1.0(65536)。
-SE_data :為1:
-則輸入數據被假定為單端信號,那么將他調整為差分信號數據,這樣就可以去除直
流流偏值。
為0:
-則輸入數據被假定為差分信號。
出口:無
功能:使用存儲在數組WindowFunc[]中的數值對Win_Array[]數組加窗
=================================================================================================*/
void WindowCalc(int Win_Array[],unsigned char SE_data)
{
#if(WINDOW_TYPE!=0) //加窗類型
IBALONG NewVal;
if(SE_data) Win_Array[0]^=0x8000; //如果數據時單端的轉換為差分的
NewVal.l=(long)Win_Array[0]*WindowFunc[0]; //加窗
if((NewVal.l<0)&&(NewVal.i[1])) Win_Array[0]=NewVal.i[0]+1;
else Win_Array[0]=NewVal.i[0];
if(SE_data) Win_Array[NUM_FFT/2]^=0x8000; //如果數據時單端的轉換為差分的
for(index=1;index<NUM_FFT/2;index++)
{
if(SE_data) Win_Array[index]^=0x8000; //數組的1到(NUM_FFT/2 - 1)
NewVal.l=(long)Win_Array[index]*WindowFunc[index];
if((NewVal.l<0)&&(NewVal.i[1])) Win_Array [index]=NewVal.i[0]+1;
else Win_Array[index]=NewVal.i[0];
if(SE_data) Win_Array[NUM_FFT-index]^=0x8000; //數組的(NUM_FFT/2 + 1)到(NUM_FFT - 1)
NewVal.l=(long)Win_Array[NUM_FFT-index]*WindowFunc[index];
if((NewVal.l<0)&&(NewVal.i[1])) Win_Array[NUM_FFT-index]=NewVal.i[0]+1;
else Win_Array[NUM_FFT-index]=NewVal.i[0];
}
#endif
#if(WINDOW_TYPE==0) //不加窗
if(SE_data) //如果數據時單端的
{ //轉換為差分的
for(index=0;index<NUM_FFT;index++) Win_Array[index]^=0x8000;//最高位通過和1取異或取反
}
#endif
}
/*=================================================================================================
03.名稱:BitReverse
入口:BR_Array[]:
-操作的對象數組。
出口:無
功能:對經過為反向的地址重新排序
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -