📄 main.c
字号:
/*-------------------------------------------------------------------------------------------------
文件名称:Main.c
创建日期:07.07.30
修改日期:
文件说明:功能:
-基于C8051F000系列单片机的FFT试验程序
创建人: 李大伟
-------------------------------------------------------------------------------------------------*/
#include <stdio.h>
#include <intrins.h>
#include <math.h>
#include "C8051F000.h"
#include "CalcPhase.h"
//ADC0寄存器定义
#define NUM_FFT 128
sfr16 ADC0 = 0xBE;
//外部XRAM数据的起始
#define DATA_BEGIN 0x0000
#define EnableInt() EIE2|=0x02
#define UnEnableInt() EIE2&=~0x02
#define SendChar(charr) SBUF=charr; while(!TI); TI=0
#define GoToInSide() P1|=0x18; P1&=~0x10 //切换到内光路
#define GoToOutSide() P1|=0x18; P1&=~0x08 //切换到外光路
#define RuleOne() P1|=0x06; AMX0SL=0x07;P2|= 0x01 //以2.5 m测尺测量
#define RuleTwo() AMX0SL=0x06;P1|=0x06; P1&=~0x06 //以25 m测尺测量
#define RuleThr() AMX0SL=0x06;P1|=0x06; P1&=~0x04 //以250 m测尺测量
#define RuleFor() AMX0SL=0x06;P1|=0x06; P1&=~0x02 //以2500 m测尺测量
#define RuleFir() AMX0SL=0x06;P1|=0x06; P1&=~0x02 //以25000m测尺测量
#define JstIntLgh() ErrSta=JudgeLightInSide() //调节内光路光强
#define JstOutLgh(a) ErrSta=JudgeLightOutSide(a);if(ErrSta) return 0 //外光路光强判断
#define ONEPI 3.1415926535897932384626433832795 //pi
#define TWOPI 6.283185307179586476925286766559 //pi*2
#define HALFPI 1.5707963267948966192313216916398 //pi/2
#define ONEHALFPI 4.7123889803846898576939650749193 //pi*1.5
#define RULER0 2.5274651209813304576396845723529 //2.5 m尺长
#define RULER1 25.274651209813304576396845723529 //25 m尺长
#define RULER2 252.74651209813304576396845723529 //250 m尺长
#define RULER3 2527.4651209813304576396845723529 //2500m尺长
#define HALFRULER0 1.263732560490665228819842286176
#define HALFRULER1 12.63732560490665228819842286176
#define HALFRULER2 126.3732560490665228819842286176
#define AVGNUM 7
//函数申明
float MeasureDistance(void);
void SysInit(void);
void DataUnite(void);
void PrtChr(unsigned char TemChr);
void ADC0_ISR(void);
float SignleMeasure(float RulerLenght);
float MeasureSub(void);
//全局变量
//FFT的XRAM空间=NUM_FFT*4字节(起始于DATA_BEGIN)
int xdata Real[NUM_FFT] _at_ DATA_BEGIN;
#if(NUM_FFT>=256)
unsigned int index,ADC_Index;
#endif
#if(NUM_FFT<256)
unsigned char index,ADC_Index;
#endif
bit Conversion_Set_Complete; //一轮采样结束标志位
int MaxVal; //一轮采样中数据的最大值
int MinVal; //一轮采样中数据的最小值
float LengthResult; //测距结果
unsigned char FlgEn; //数据有效标志
unsigned char ErrSta; //全局错误代码
unsigned char AvgeTimes; //平均次数
unsigned char SampeEnable; //采样允许标志
unsigned char MesuState; //测量状态标志
unsigned char MesuEnable; //测量允许标志
/*=================================================================================================
01.名称:main
入口:无
出口:无
功能:系统主函数
=================================================================================================*/
void main()
{
long TemLVal;
float TemFVal;
unsigned char TemBuf;
SysInit();
while(1)
{
while(!RI); RI=0;
TemBuf=SBUF;
switch(TemBuf)
{
case 0xBB:
SendChar(0xBB);
break;
case 0xB4:
SendChar(0xB4); //k=justlight();
if(ErrSta)
{
if(ErrSta==1) {ErrSta=0;PrtChr(0x11);} //光太弱
else if(ErrSta==2) {ErrSta=0;PrtChr(0x22);} //光太强
break;
}
LengthResult=MeasureDistance(); //测距
if(ErrSta)
{
if(ErrSta==1) {ErrSta=0;PrtChr(0x11);} //光太弱
else if(ErrSta==2) {ErrSta=0;PrtChr(0x22);} //光太强
break;
}
if(FlgEn) //数据有效
{ //将数据发给主板
SendChar(0xDD);
TemLVal=(long)LengthResult;
SendChar(TemLVal/1000); //千位
SendChar((((TemLVal%1000)/100)<<4)|((TemLVal%1000)%100)/10); //百位和十位
ErrSta=((TemLVal%1000)%100)%10;
TemFVal=LengthResult-(float)TemLVal;
TemLVal=(long)(TemFVal*1000);
SendChar((ErrSta<<4)|(TemLVal/100));ErrSta=0; //个位和十分位
SendChar((((TemLVal%100)/10)<<4)|((TemLVal%100)%10)); //百分位和千分位
SendChar(0x0d);
}
else PrtChr(0x33);
break;
case 0xB7: //打开关闭激光指示
SendChar(0xB7);
if((P1&0x08)==0x08) {GoToOutSide();} //外光路
else {GoToInSide ();} //内光路
break;
case 0xB8: //发送高压值给主板
SendChar(0xB8);
SendChar(0xB8);
MaxVal=(DAC0H<<8)|DAC0L;
SendChar(((MaxVal/1000)<<4)|((MaxVal%1000)/100));
SendChar(((((MaxVal%1000)%100)/10)<<4)|(((MaxVal%1000)%100)%10));
SendChar(0x0D);
break;
default:
break;
}
}
}
/*=================================================================================================
02.名称:SysInit
入口:tem - 要发送的字符,占一个字节
出口:无
功能:通过串口与主板通讯
=================================================================================================*/
void SysInit(void)
{
WDTCN = 0xDE; //关看门狗
WDTCN = 0xAD;
OSCXCN = 0x20; //外部时钟输入@19.44MHz
OSCICN = 0x08;
XBR0 = 0x07; //配置交叉开关
XBR2 = 0x41;
CKCON = 0x20; //配置定时器2作为波特率发生器
TMOD = 0x30; //8为异步
T2CON = 0x34;
RCAP2L = 0xC1; //9600@19.44MHz
RCAP2H = 0xFF;
SCON = 0x50; //UART
REF0CN = 0x03; //参考电压
DAC0CN = 0x80; //ADC
AMX0SL = 0x06;
ADC0CF = 0x80;
ADC0CN = 0xC8;
P1=0xff;
P0=0x0;
P2&=~0x01;
P1&=~0x80;
P1&=~0x40;
DAC0L&=0x0;
DAC0H&=0x0;
DAC0L|=0x6a; //设置高压值
DAC0H|=0x05;
FlgEn = 1; //初始化变量及标志
ErrSta = 0;
ADC_Index = 0;
SampeEnable = 0;
MesuState = 0;
IE = 0x80; //中断使能
}
/*=================================================================================================
02.名称:PrtChr
入口:tem - 要发送的字符,占一个字节
出口:无
功能:通过串口与主板通讯
=================================================================================================*/
void PrtChr(unsigned char TemChr)
{
SendChar(0xDD); //无效
SendChar(TemChr); //千位
SendChar(TemChr);
SendChar(TemChr);
SendChar(TemChr);
SendChar(0x0D);
}
/*=================================================================================================
01.名称:MeasureDistance
入口:无
出口:DisVal0:返回单次测距值
功能:单次测量函数
=================================================================================================*/
float MeasureDistance(void)
{
float xdata DisVal0,DisVal1,DisVal2,DisVal3;//;
unsigned char N0,N1,N2;
RuleFor();
DisVal3=RULER3-SignleMeasure(RULER3);
RuleThr();
DisVal2=SignleMeasure(RULER2);
RuleTwo();
DisVal1=SignleMeasure(RULER1);
RuleOne();
DisVal0=SignleMeasure(RULER0);
/*
RuleOne();
//JstOutLgh();
DisVal0=SignleMeasure(RULER0);
P2&=~0x01;
//SelChlZer();
RuleTwo();
DisVal1=SignleMeasure(RULER1);
//SelChlSix();
RuleThr();
DisVal2=SignleMeasure(RULER2);
//SelChlSix();
RuleFor();
DisVal3=SignleMeasure(RULER3);
//SelChlSix();
*/
DisVal3+=((float)HALFRULER2-DisVal2/2);
DisVal2+=((float)HALFRULER1-DisVal1/2);
DisVal1+=((float)HALFRULER0-DisVal0/2);
N0=(unsigned char)(((DisVal1-DisVal0)/RULER0)+0.5);
N1=(unsigned char)(((DisVal2-DisVal1)/RULER1)+0.5);
N2=(unsigned char)(((DisVal3-DisVal2)/RULER2)+0.5);
DisVal0+=(10*N1+N0)*RULER0;//100*N2+
return DisVal0;
}
/*=================================================================================================
01.名称:SignleMeasure
入口:RulerLenght: 测尺长度
出口:返回单测尺测距值
功能:单测尺一次测量函数
=================================================================================================*/
float SignleMeasure(float rl)
{
float xdata Ph1,Ph2,Ph3;
long DelayA,DelayB;
unsigned char i;
DelayA=65000;
DelayB=65000;
ADC_Index = 0;
SampeEnable=0;
MesuState=0;
MesuEnable=0;
for(i=0;i<NUM_FFT;i++)
{
Real[i]=0;
}
GoToInSide();//内
while(DelayA--);
MesuState=1;
AvgeTimes=AVGNUM;
EnableInt();
while(MesuState);
for(i=0;i<NUM_FFT;i++)
{
Real[i]=(int)(((float)Real[i]/AVGNUM)+0.5);//Real[i]/AVGNUM;
}
Ph1=rl*(GetPhaseFromMeasDat(Real)/2500.0);
for(i=0;i<NUM_FFT;i++)
{
Real[i]=0;
}
GoToOutSide();//外
while(DelayB--);
MesuState=1;
AvgeTimes=AVGNUM;
while(MesuState);
UnEnableInt();
for(i=0;i<NUM_FFT;i++)
{
Real[i]=(int)(((float)Real[i]/AVGNUM)+0.5);//Real[i]/AVGNUM;
}
Ph2=rl*(GetPhaseFromMeasDat(Real)/2500.0);
if(Ph1-Ph2<0.0000001) Ph3=Ph2-Ph1; //NOW
else Ph3=rl-(Ph1-Ph2);
return Ph3;
}
/*=================================================================================================
12.名称:ADC0_ISR
入口:无
出口:无
功能:ADC0中断服务子程序
=================================================================================================*/
void ADC0_ISR(void) interrupt 15 using 3
{
int ADCSamp;
ADCINT=0; //清ADC转换标志位
if(SampeEnable==1)
{
ADCSamp=ADC0; //存ADC的转换值
if(MaxVal<=ADCSamp) MaxVal=ADCSamp;
if(MinVal>=ADCSamp) MinVal=ADCSamp;
Real[ADC_Index]+=ADCSamp;
ADC_Index++; //采样次数加1
if(ADC_Index>=NUM_FFT) //达到采样数
{
ADC_Index=0;
AvgeTimes--;
if(AvgeTimes==0)
{
SampeEnable=0;
MesuState=0;
}
}
}
else
{
ADC_Index++;
if(ADC_Index>=NUM_FFT||MesuState==1)
{
if(MesuState==1&&ADC_Index==NUM_FFT)
{
SampeEnable=1;
MaxVal=0;
MinVal=4096;
ADC_Index=0;
}
else if(ADC_Index==NUM_FFT) ADC_Index=0;
}
}
}
/*-----------------------------------------------------------------------------------------------*/
//End FFT_New_test.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -