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

📄 main.c

📁 在c8051f015单片机上实现最小二乘法曲线拟合算法
💻 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 + -