⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fft_new_test.c

📁 在c8051平台上实现的FFT运算
💻 C
📖 第 1 页 / 共 2 页
字号:
/*-------------------------------------------------------------------------------------------------
文件名称: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 + -