📄 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 + -