/*****************************************
*AD程序
*编写：李平
*版本号：V1.00
*日期：2011-7-16
*文件名：Ad.c
*/
#include "Ad.h"
#include "flash.h"
#include "usart.h"
#include "buffer.h"

#define ZERO		500000
#define SPANZERO  	ZERO
#define TRN_INI   	2

extern unsigned char usart1_send_data[64];
extern void USART_Send_DMA(unsigned char j,int n);

extern unsigned char WeightConst_ChanCheShu;
ulng keyword=0;

uchar stas_s0=0;//状态标志变量  0：称重状态 1：工厂标定和工厂设置状态   2：用户设置状态

uchar fs[16]= {0}; //工厂参数

uchar ZeroPass=0;
uchar IsRealZero=0;
uchar IsZeroFlag=0;
uchar num_stbn=0;
uchar n_stbn=0;
uchar num_trn=0;
uchar stbn=0;
uchar IsStb=0;
uchar Isol=0;
uchar ad_nag_flag=0;
uchar nag=0;
uchar IsTare=0;
ulng ad_lcd=0;
ulng ad_lcd1=0;
ulng ad_read=0;
ulng ad_start=0;
ulng ad_sample=0;
ulng ad_zero=0;
ulng real_zero=0;
ulng ad_last=0;
ulng ad_tare=0;
ulng Maxval=0;
uchar Inteval=0;
uchar point1=0;
uchar point2=0;
float spanz=0;
ulng Low_w=0;
ulng Up_w=0;
ulng err_cnt=0;
ulng ok_cnt=0;
uchar STB_N=2;
uchar start_loop;
ulng AD=0;
/*******************************************/

float Avad[6]= {0};
float Bvad[6]= {0};
float Cvad[6]= {0};
float Dvad[6]= {0};
float Evad[6]= {0};
float Fvad[6]= {0};
float Gvad[6]= {0};
float Hvad[6]= {0};
float Ivad[6]= {0};
float Jvad[6]= {0};
float AD_result=0;

uchar ad_ini_flag=0;
uchar ad_ini_flag1=0;
float Ad_tol=0;
uchar Ad_cnt=0;
uchar Ad_I=0;
uchar AVG_CNT=4;

uchar f_zeroset=1;

uchar FLT_CNT=16;
uchar FLT_XF_CNT=1;
ulng FilterArray[128];
uchar FilterPos=0;
uchar dat[32]= {0};

ulng Kalman_FilterArray[128];
uchar Kalman_ini_flag=0;
uchar Kalman_FilterPos=0;

uchar key_CNT_f=0;
float percent_fl=1.000f;
ulng percent_ul=999;
extern uchar ini_flag1;

uchar Rsbuffer[7]= {0}; //RS232使用

uchar RsWeight[]=
{
    0x30,0x31,0x32,0x33,0x34,0x35,
//	"0"	 "1"  "2"  "3"  "4"  "5"
    0x36,0x37,0x38,0x39
//	"6"	 "7"  "8"  "9"
};

float x1=0,x2=0,x0=0,y0=0,y1=0,y2=0;
unsigned	char	buf[4] = {0,0,0,0};
unsigned	char isIRQ;
ulng ad_sample_temp;
extern void Delay(__IO uint32_t nCount);
#define  _nop_()		Delay(1)

ulng get_weight(void)
{
	  ulng tempval=0;
    isIRQ=0;
	  tempval = Ad_Sample1();
	  if (tempval<0xFFFFFFFF)
	  {
      ad_sample_temp = tempval;
	  }

   // if (ad_sample_temp>0 && ad_sample_temp<0xFFFFF && isIRQ==0)
	  if (isIRQ==0 && tempval<0xFFFFFFFF)
        ad_sample=ad_sample_temp;
    // ad_sample_=ad_sample;
    //  ad_sample=(int)((float)ad_sample * 0.01 + (1.0 - 0.01) * (float)ad_sample);
    ad_sample = AdFilter_xf(ad_sample);  //限幅滤波	 FLT_XF_CNT=32;
    switch(fs[1])
    {
		case 1:
        ad_sample = Kalman_Filter(ad_sample, 0.5, 0.5);
        break;
		case 2:
        ad_sample = Kalman_Filter(ad_sample, 0.1, 0.5);
        break;
		case 3:
        ad_sample = Kalman_Filter(ad_sample, 0.05, 0.5);
        break;
    case 4:
        ad_sample = Kalman_Filter(ad_sample, 0.01, 0.5);
        break;
    case 5:
        ad_sample = Kalman_Filter(ad_sample, 0.1, 0.5);
        break;
    case 6:
        ad_sample = Kalman_Filter(ad_sample, 0.05, 0.5);
        break;
    case 7:
        ad_sample = Kalman_Filter(ad_sample, 0.1, 0.5);
        break;
    default:
        ad_sample = Kalman_Filter(ad_sample, 0.125, 0.5);
        break;
    }
    ad_sample = AdFilter(ad_sample);     //滑动滤波	  FLT_CNT=32;
    ad_read = adcalculate(ad_sample);
    Common();  //称量状态


    RS232weight(ad_lcd1);
    return ad_lcd1;
}



//---------------------------------
//Function that writes to the AD7190 via the SPI port.
//--------------------------------------------------------------------------------
void WriteToAD7190(unsigned char count, unsigned char *buf)
{
    unsigned	char	ValueToWrite = 0;
    unsigned	char	i = 0;
    unsigned	char	j = 0;

   // __disable_irq();
    AD_CLK_1;
    _nop_();

    for(i=count; i>0; i--)
    {
        ValueToWrite = *(buf + i - 1);
        for(j=0; j<8; j++)
        {
            AD_CLK_0;
            if(0x80 == (ValueToWrite & 0x80))
            {
                AD_DIN_1;	  //Send one to SDO pin
            }
            else
            {
                AD_DIN_0;  //Send zero to SDO pin
            }
            _nop_();
            AD_CLK_1;
            _nop_();
            ValueToWrite <<= 1;	//Rotate data
        }
    }
    AD_DIN_0;
  //  __enable_irq();
}
//---------------------------------
//Function that reads from the AD7190 via the SPI port.
//--------------------------------------------------------------------------------
void ReadFromAD7190(unsigned char count, unsigned char *buf)
{
    unsigned	char	i = 0;
    unsigned	char	j = 0;
    unsigned	int  	iTemp = 0;
    unsigned	char  RotateData = 0;
   // __disable_irq();
    AD_CLK_1;
    _nop_();

    for(j=count; j>0; j--)
    {
        for(i=0; i<8; i++)
        {
            AD_CLK_0;
            RotateData <<= 1;		//Rotate data
            _nop_();
            iTemp = AD_R_DI;			//Read SDI of AD7190
            AD_CLK_1;
            if(0x00000001 == (iTemp & 0x00000001))
            {
                RotateData |= 1;
            }
            _nop_();
        }
        *(buf + j - 1)= RotateData;
    }
   // __enable_irq();
}

// extern void led_change(void);
/***********************************
*读AD7190函数
*/
ulng Ad_Sample1(void)
{
    uchar i;
    ulng j=0;
    ulng AdSample=0XFFFFFFFF;

    // __disable_irq();
    AD_CLK_1;
    _nop_();
 //   _nop_();
    while(AD_R_DI==1) {
        j++;
        if (j>1000) break;
    }
    if (j<1000)
    {
        AdSample=0;
        for(i=0; i<24; i++)
        {
            AD_CLK_0;
        //    _nop_();
            _nop_();
            AdSample<<=1;
            if(AD_R_DI==1)
                AdSample++;

            AD_CLK_1;
            _nop_();
       //     _nop_();
        }
/*
        if ((AdSample&0x00800000)!=0)
        {
            AdSample=~AdSample+1;
            AdSample&=0x007fffff;
            AdSample=0x007fffff-AdSample;
        }
        else
        {
            AdSample&=0x007fffff;
            AdSample=0x007fffff+AdSample;
        }
				*/
        if (fs[1]<=4 && fs[1]>0 )
            AdSample = AdSample>>3;
        else if (fs[1]>4 && fs[1]<=6 )
            AdSample = AdSample>>2;      
        else
            AdSample = AdSample;
				
  //      led_change();
    }
    //__enable_irq();

    return(AdSample);
}

/*********************************************
*AD7190上电初始化处理
*/
void adFs(unsigned char fs_)
{
    Delay(100);
    AD_CS_0;
    AD_SYNC_1;
    Delay(100);
//Reset AD7190
    buf[2]= 0xff;
    buf[1]= 0xff;
    buf[0]= 0xff;
    WriteToAD7190(3,buf);
    buf[1]= 0xff;
    buf[0]= 0xff;
    WriteToAD7190(2,buf);
    Delay(200);
    /***********************************
    通信寄存器
    WEN|R/W|RS2|RS1|RS0|CREAD| 0 | 0
     0   0   0   0   1    0    0   0
    */
    /***********************************
    模式寄存器
    MD2|MD1|MD0|DAT_STA|CLK1|CLK0| 0 | 0
     0   0   0     0     0    0    0   0
    SINC3| 0 |ENPAR| 0 |SINGLE|REJ60|FS9|FS8
    	0    0    0    0    0      1    0   0
    FS7|FS6|FS5|FS4|FS3|FS2|FS1|FS0
     0   0   0   0   0   1   0   1
    */
//mode register
    buf[0] = 0x08;
    WriteToAD7190(1,buf);
    buf[2] = 0x00;
    buf[1] = 0x04;
//	buf[0] = 0x50;//xxx Hz
    if (fs_==0)
        buf[0] = 80;//xxx Hz
    else
        /*if (fs_==1)
        {
          buf[1] = buf[1]|((480>>8)&3);//xxx Hz
          buf[0] = 480&0xff;//xxx Hz
        }
        else if (fs_==2)
        {
          buf[1] = buf[1]|((480>>8)&3);//xxx Hz
          buf[0] = 480&0xff;//xxx Hz
        }
        else if (fs_==3)
        {
          buf[1] = buf[1]|((640>>8)&3);//xxx Hz
          buf[0] = 640&0xff;//xxx Hz
        }
        else if (fs_==4)
        {
          buf[1] = buf[1]|((640>>8)&3);//xxx Hz
          buf[0] = 640&0xff;//xxx Hz
        }
        else if (fs_==5)
        {
          buf[1] = buf[1]|((1023>>8)&3);//xxx Hz
          buf[0] = 1023&0xff;//xxx Hz
        }
        else if (fs_==6)
        {
          buf[1] = buf[1]|((1023>>8)&3);//xxx Hz
          buf[0] = 1023&0xff;//xxx Hz

        }
        else if (fs_==7)
        */
    {
        buf[1] = buf[1]|((120>>8)&3);//xxx Hz
        buf[0] = 120&0xff;//xxx Hz
    }
    /*
    else
    {
      buf[0] = 80;//xxx Hz
    }
    */
    WriteToAD7190(3,buf);

    /***********************************
    通信寄存器
    WEN|R/W|RS2|RS1|RS0|CREAD| 0 | 0
     0   0   0   1   0    0    0   0
    */
    /*********************************
    配置寄存器
    CHOP| 0 | 0 |REFSEL| 0 | 0 | 0| 0
      0   0   0     0    0   0   0  0
    CH7|CH6|CH5|CH4|CH3|CH2|CH1|CH0
     0   0   0   0   0   0   1   0
    BURN|REFDET| 0 |BUF|U/B|G2|G1|G0
     0      0    0   1   0   1  1  1
    */
//Configuration register
    buf[0] = 0x10;
    WriteToAD7190(1,buf);
    buf[2] = 0x80; //buf[2] = 0x80;
    buf[1] = 0x02;
    buf[0] = 0x17;
    WriteToAD7190(3,buf);
    /***********************************
    通信寄存器
    WEN|R/W|RS2|RS1|RS0|CREAD| 0 | 0
     0   0   1   0   1    0    0   0
    */
    /***********************************
    GPOCON寄存器
     0 |BPDSW|GP32EN|GPIOEN|P3DAT|P2DAT|P1DAT|P0DAT
     0    1      0      0      0    0     0     0
    */
//GPOCON register
    buf[0] = 0x28;
    WriteToAD7190(1,buf);
    buf[0] = 0x40;
    WriteToAD7190(1,buf);
    /***********************************
    通信寄存器
    WEN|R/W|RS2|RS1|RS0|CREAD| 0 | 0
     0   1   0   1   1    1    0   0
    */
//通信寄存器，连续读数据寄存器
    buf[0] = 0x5c;
    WriteToAD7190(1,buf);
    Delay(5);
}

/*********************************************
*AD7190上电初始化处理
*/
void adini(void)
{
    Delay(100);
    AD_CS_0;
    AD_SYNC_1;
    Delay(100);
//Reset AD7190
    buf[2]= 0xff;
    buf[1]= 0xff;
    buf[0]= 0xff;
    WriteToAD7190(3,buf);

    buf[1]= 0xff;
    buf[0]= 0xff;
    WriteToAD7190(2,buf);
    Delay(200);
    /***********************************
    通信寄存器
    WEN|R/W|RS2|RS1|RS0|CREAD| 0 | 0
     0   0   0   0   1    0    0   0
    */
    /***********************************
    模式寄存器
    MD2|MD1|MD0|DAT_STA|CLK1|CLK0| 0 | 0
     0   0   0     0     0    0    0   0
    SINC3| 0 |ENPAR| 0 |SINGLE|REJ60|FS9|FS8
    	0    0    0    0    0      1    0   0
    FS7|FS6|FS5|FS4|FS3|FS2|FS1|FS0
     0   0   0   0   0   1   0   1
    */
//mode register
    buf[0] = 0x08;
    WriteToAD7190(1,buf);
    buf[2] = 0x00;
    buf[1] = 0x04;
    buf[0] = 0x50;//xxx Hz
    WriteToAD7190(3,buf);
    /***********************************
    通信寄存器
    WEN|R/W|RS2|RS1|RS0|CREAD| 0 | 0
     0   0   0   1   0    0    0   0
    */
    /*********************************
    配置寄存器
    CHOP| 0 | 0 |REFSEL| 0 | 0 | 0| 0
      0   0   0     0    0   0   0  0
    CH7|CH6|CH5|CH4|CH3|CH2|CH1|CH0
     0   0   0   0   0   0   1   0
    BURN|REFDET| 0 |BUF|U/B|G2|G1|G0
     0      0    0   1   0   1  1  1
    */
//Configuration register
    buf[0] = 0x10;
    WriteToAD7190(1,buf);
    buf[2] = 0x00;
    buf[1] = 0x02;
    buf[0] = 0x17;
    WriteToAD7190(3,buf);
    /***********************************
    通信寄存器
    WEN|R/W|RS2|RS1|RS0|CREAD| 0 | 0
     0   0   1   0   1    0    0   0
    */
    /***********************************
    GPOCON寄存器
     0 |BPDSW|GP32EN|GPIOEN|P3DAT|P2DAT|P1DAT|P0DAT
     0    1      0      0      0    0     0     0
    */
//GPOCON register
    buf[0] = 0x28;
    WriteToAD7190(1,buf);
    buf[0] = 0x40;
    WriteToAD7190(1,buf);
    /***********************************
    通信寄存器
    WEN|R/W|RS2|RS1|RS0|CREAD| 0 | 0
     0   1   0   1   1    1    0   0
    */
//通信寄存器，连续读数据寄存器
    buf[0] = 0x5c;
    WriteToAD7190(1,buf);
    Delay(5);
}
/************************
*AD采样速度选择函数
*/
void Speed(void)
{
    switch(fs[1])
    {
    case 0:
        ad_ini_flag=0;
        ad_ini_flag1=0;
        FLT_CNT=4;      //滑动滤波
        AVG_CNT=4;      //平均滤波
        break;
    case 1:
        ad_ini_flag1=0;
        FLT_CNT=24;
        AVG_CNT=6;
        break;
    case 2:
        ad_ini_flag1=0;
        FLT_CNT=24;
        AVG_CNT=6;
        break;
    case 3:
        ad_ini_flag1=0;
        FLT_CNT=24;
        AVG_CNT=6;
        break;
    case 4:
        ad_ini_flag1=0;
        FLT_CNT=24;
        AVG_CNT=6;
        break;
    case 5:
        ad_ini_flag1=0;
        FLT_CNT=24;
        AVG_CNT=6;
        break;
    case 6:
        ad_ini_flag1=0;
        FLT_CNT=24;
        AVG_CNT=6;
        break;
    case 7:
        ad_ini_flag1=0;
        FLT_CNT=24;
        AVG_CNT=6;
        break;
    default:
        ad_ini_flag1=0;
        FLT_CNT=32;
        AVG_CNT=4;
        break;
    }
}

/****限幅滤波**********************/
uchar count_xf;
ulng AdFilter_xf_value;
uchar ad_ini_flag_xf=0;

ulng AdFilter_xf(ulng x) {
    uint32_t FILTER_A = 0x7FFF; //限幅100公斤
    int32_t FILTER_1 ;
    if(ad_ini_flag_xf==0)
    {
        ad_ini_flag_xf=1;
        count_xf=0;
        AdFilter_xf_value=x;
        return x;
    }
    FILTER_1 = x - AdFilter_xf_value;
    if (FILTER_1<0)
        FILTER_1 = FILTER_1 * -1;

    if(FILTER_1 > FILTER_A  && count_xf<=FLT_XF_CNT)
    {
        count_xf++;
    }
    else
    {
        count_xf=0;
        AdFilter_xf_value = x;
    }
    return AdFilter_xf_value;
}

/***kalman滤波*************/
/*
        Q:过程噪声，Q增大，动态响应变快，收敛稳定性变坏
        R:测量噪声，R增大，动态响应变慢，收敛稳定性变好
*/
ulng Kalman_Filter(const double ResrcData, double ProcessNiose_Q,double MeasureNoise_R)
{
    int32_t ad_sum = 0;
    ulng ad_avg = 0;
    double R = MeasureNoise_R;
    double Q = ProcessNiose_Q;
    static double x_last;
    static double p_last;

    double x_mid;
    double x_now;
    double p_mid ;
    double p_now;
    double kg;

    uchar i;
    uchar x__=3;
    uchar y__=1<<x__;
    if(Kalman_ini_flag==0)
    {
        for(i=0; i<y__; i++)
            Kalman_FilterArray[i]=0;

        Kalman_ini_flag=1;
    }

    Kalman_FilterPos++;
    if (Kalman_FilterPos>=y__)
        Kalman_FilterPos=0;

    Kalman_FilterArray[Kalman_FilterPos]=ResrcData;
    ad_sum = 0;
    for (i=0; i<y__; i++)
        ad_sum+=Kalman_FilterArray[i];

    ad_avg = ad_sum>>x__;
    ad_sum = 0;
//	for (i=0; i<y__; i++)
//	    ad_sum+=(int)(Kalman_FilterArray[i]-ad_avg)*(int)(Kalman_FilterArray[i]-ad_avg);
//
//	R = (ad_sum>>(x__+2));
    for (i=0; i<y__; i++)
        ad_sum+=(Kalman_FilterArray[i]-ad_avg);
    if (ad_sum <0) ad_sum=ad_sum*-1;
//	R = 1<<ad_sum;


    x_mid=x_last;          //x_last=x(k-1|k-1),x_mid=x(k|k-1)
    p_mid=p_last+Q;        //p_mid=p(k|k-1),p_last=p(k-1|k-1),Q=噪声
    kg=p_mid/(p_mid+R);    //kg为kalman filter，R为噪声
    x_now=x_mid+kg*(ResrcData-x_mid); //估计出的最优值

    p_now=(1-kg)*p_mid;               //最优值对应的covariance

    p_last = p_now;                   //更新covariance值
    x_last = x_now;                   //更新系统状态值

    return x_now;
}

/****************************/
ulng AdFilter(ulng x)
{
    ulng ad_sum = 0;
    uchar i;

    if(ad_ini_flag1==0)
    {
        for(i=0; i<FLT_CNT; i++)
        {
            FilterArray[i]=x;
        }
        ad_ini_flag1=1;
        return x;
    }

    FilterPos++;
    if (FilterPos>=FLT_CNT)
    {
        FilterPos=0;
    }

    FilterArray[FilterPos]=x;

    for (i=0; i<FLT_CNT; i++)
    {
        ad_sum+=FilterArray[i];
    }

    return(ad_sum/(FLT_CNT));
}


/***************************
*标定系数保存
*地址：33--52
*/
void ArgSave(void)
{
		ad_Maxval =	Maxval;
		ad_Inteval = Inteval;
		ad_Point = point1;
		ad_Spanz = spanz;
		ad_Zero	= ad_zero;
		write_Flash("ad_Maxval", &ad_Maxval, sizeof(ad_Maxval));					
		write_Flash("ad_Inteval", &ad_Inteval, sizeof(ad_Inteval));					
		write_Flash("ad_Point", &ad_Point, sizeof(ad_Point));		
		write_Flash("ad_Spanz", &ad_Spanz, sizeof(ad_Spanz));					
		write_Flash("ad_Zero", &ad_Zero, sizeof(ad_Zero));						

    W_fs();
    if((stas_s0==0)||(stas_s0==1))
        Zero_Save();
}
/***************************
*标定系数读出
*地址：32--52
*/
void ArgRead(void)
{						
		Maxval = ad_Maxval;
		Inteval = ad_Inteval;
		point1 = ad_Point;
		spanz = ad_Spanz;
		ad_zero = ad_Zero;
    point2=0;
	
    adini();
    R_fs();
    Zero_Read();

    Speed();
    adFs(fs[1]);
}

/**********************************
*写工厂设置参数
*固定地址：1-16
*/
void W_fs(void)
{
		ad_FS = fs[1];
	  write_Flash("ad_FS", &ad_FS, sizeof(ad_FS));						
}
/***************************
*读工厂设置参数
*固定地址：1-16
*/
void R_fs(void)
{
    fs[1] = ad_FS;	
}

/************************************
*标定参数默认值
*/
void ArgIni(void)
{
    fs[1]=0;
    Maxval=3000;
    spanz=0.5;
    Inteval=1;
    point1=3;
    point2=0;
    ad_zero=ZERO;
}
/************************************
*零点参数保存
*地址 53--56
*/
void Zero_Save(void)
{
		ad_Tare = ad_tare;	
	  write_Flash("ad_Tare", &ad_Tare, sizeof(ad_Tare));	
}
/************************************
*零点参数读出
*地址 53--56
*/
void Zero_Read(void)
{
   ad_tare = ad_Tare;	
}


/*************************************
Description: 转换十进制至bcd准备显示(重量)
Argument:	none
Return:		none
*************************************/
void DisplayWeight_ww(__IO ulng dis_data)
{
    uchar digit;
    ulng divider=100000;   		//除数
    uchar quotient=0;           	//商
    if(dis_data>999999)
    {
        dis_data=0;				//超过显示最大值送零
    }
    for(digit=0; digit<6; digit++)
    {
        quotient=0;
        while(dis_data>(divider-1))
        {
            dis_data-=divider;
            quotient++;
        }
        divider/=10;
        Rsbuffer[digit]=RsWeight[quotient];
    }
}

void RS232weight(__IO ulng x)
{
    DisplayWeight_ww(x);
    //2D 33 36 35 34 0D
    //02 2B 30 30 30 30 30 30 33 03
    // 30 30 2E 30 30 30 0D 0A

    if (WeightConst_ChanCheShu==9)
    {
			  usart1_send_data[0] = 0x04;
			  usart1_send_data[1] = (ad_sample_temp>>24)&0xFF;
			  usart1_send_data[2] = (ad_sample_temp>>16)&0xFF;
			  usart1_send_data[3] = (ad_sample_temp>>8)&0xFF;
			  usart1_send_data[4] = ad_sample_temp&0xFF;
    }
    else
    {
			  usart1_send_data[0] = 0x06;
        if (nag)
        {
					  usart1_send_data[1] = 0x2D;
            for(int i=2; i<6; i++) usart1_send_data[i] = Rsbuffer[i];
        }
        else
            for(int i=1; i<6; i++) usart1_send_data[i] = Rsbuffer[i];
				
    }
		usart1_send_data[6] = 0x0D;
		rt_sem_take(uart1_lock, RT_WAITING_FOREVER);
    HAL_UART_Transmit_DMA(&huart1, usart1_send_data, usart1_send_data[0]);
		rt_sem_release(uart1_lock);
}
/*********************************
*小数点位  1-5
*/
void setPoint(__IO uchar val_)
{
    point1 = val_;
    ArgSave();
}
/*********************************
*分度值  1、2、5、10
*/
void setInteval(__IO uchar val_)
{
    Inteval=val_;
    ArgSave();
}

/*********************************
*滤波级别 1-8
*/
void setFS(__IO uchar val_)
{
    fs[1] = val_;

    adFs(fs[1]);
    Speed();
    ArgSave();
}

/*********************************
*校正百分比
*/
void setPercent(__IO int val_)
{
    percent_fl=(float)val_/1000;
    spanz = spanz + spanz * percent_fl;      //保存新的校正
    ArgSave();
}

/*********************************
*最大称量
*/
void setMaxval(__IO ulng val_)
{
    Maxval = val_;
    ArgSave();
}

/*********************************
*0点校正
*/
void setZeroCal(void)
{
    if ((ad_sample>0)&&(ad_sample<50000000))
    {
        zerocalculate();   //0点计算
        ArgSave();
    }
}

/*********************************
*砝码校正
*/
void setFullCal(__IO ulng val_)
{
    keyword = val_;
    if ((ad_sample-ad_zero)>=(keyword/Inteval*10)&&(ad_sample>ad_zero)&&(keyword!=0))
    {
        fullcalculate();       //砝码计算
        ArgSave();
    }
}

/*********************************
*置零
*/
void setZero(void)
{
    Zero_Pro();
}
/*********************************
*称量计算显示函数
*/
void Common(void)
{
    if(f_zeroset==0)
    {
        CommonModeIni();
    }
    CheckZero(ad_read);
    Do();
    Dis_Weight();
}
/*********************************************
*零点检测
*/
void CheckZero(__IO ulng check_data)
{
    ulng zero_range;
    zero_range=24;
    if(check_data>real_zero)
    {
        check_data-=real_zero;
    }
    else
    {
        check_data=real_zero-check_data;
    }
    IsRealZero=(check_data<zero_range);
    IsZeroFlag=IsRealZero;
}
/*********************************************
*初始零点建立
*/
void CommonModeIni(void)
{
    IsStb=0;
    while(!IsStb)
    {
        ad_sample=Ad_Sample1();
        ad_sample=AdFilter(ad_sample);
        ad_sample=EX_QR_Filter(ad_sample);
        ad_read=adcalculate(ad_sample);
        Check_Wen1();
        ad_last=ad_read;
    }
    Zero_Read();
    ad_read=ad_tare;
    ad_lcd=ad_read;
    ad_start=ad_read;
    ad_last=ad_read;
    real_zero=ad_read;
    f_zeroset=1;
}
/*********************************************
*开机稳定判别
*/
void Check_Wen1(void)
{
    ulng check_Wdata1;
    ulng check_Wdata2;
    ulng stb_w;

    stb_w=50;

    check_Wdata1 = ad_last - stb_w;
    check_Wdata2 = ad_last + stb_w;
    if((ad_read>check_Wdata1)&&(ad_read<check_Wdata2))
    {
        if(n_stbn>=20)
        {
            n_stbn=0;
            IsStb=1;
        }
        else
        {
            n_stbn++;
        }
    }
    else
    {
        n_stbn=0;
    }
}
/*********************************************
*稳定判别
*/
void Check_Wen(void)
{
    ulng check_Wdata1;
    ulng check_Wdata2;
    ulng stb_w;

    stb_w=5;
    STB_N=5;

    check_Wdata1 = ad_last - stb_w;
    check_Wdata2 = ad_last + stb_w;
    if((ad_read>check_Wdata1)&&(ad_read<check_Wdata2))
    {
        if(n_stbn>=STB_N)
        {
            n_stbn=0;
            IsStb=1;
        }
        else
        {
            n_stbn++;
        }
    }
    else
    {
        n_stbn=0;
    }
}
/*********************************************
*不稳定判别
*/
void Check_Not_Wen(void)
{
    ulng check_data1;
    ulng check_data2;
    ulng nstb_w;

    nstb_w=10;

    check_data1=ad_lcd-nstb_w;
    check_data2=ad_lcd+nstb_w;
    if((ad_read<check_data1)||(ad_read>check_data2))
    {
        IsStb=0;
    }
}
/*********************************************
*开机零点检测
*Return: 0 开机零点超出范围
*	  1 开机零点在范围内
*/
uchar Check_Start(void)
{
    ulng check1=0;
    ulng check2=0;

    check1=SPANZERO-(Maxval/(ulng)Inteval*2);//20%
    check2=SPANZERO+(Maxval/(ulng)Inteval*2);

    if((ad_read<check1)||(ad_read>check2))
    {
        return(0);
    }
    else
    {
        return(1);
    }
}
/*********************************************
*零点跟踪
*/
void Zero_Trace(void)
{
    ulng check_data1;
    ulng check_data2;
    ulng ZeroTrace_w;
    uchar trn_cnt;

    ZeroTrace_w = 5;

    check_data1=ad_start-Maxval/((ulng)Inteval*2)/10;//600;
    check_data2=ad_start+Maxval/((ulng)Inteval*2)/10;//600;
    if((ad_read<check_data1)||(ad_read>check_data2))
    {
        num_trn=0;
        return;
    }
    check_data1=real_zero-1;
    check_data2=real_zero+1;

    if((ad_read>=check_data1)&&(ad_read<=check_data2))
    {
        num_trn=0;
        return;
    }
    check_data1=real_zero-ZeroTrace_w;
    check_data2=real_zero+ZeroTrace_w;
    if((ad_read<=check_data1)||(ad_read>=check_data2))
    {
        num_trn=0;
        return;
    }
    trn_cnt=5;
    if(num_trn>=trn_cnt)
    {
        if (ad_read>=real_zero)
        {
            real_zero++;
            ad_tare++;

        }
        else
        {
            real_zero--;
            ad_tare--;
        }
        num_trn=0;
    }
    else
    {
        num_trn++;
    }
}


/*********************************************
*四舍五入计算
*/
ulng RoundOff(__IO ulng data1,__IO ulng data2)
{
    ulng result;
    ulng remainder;
    result=data1/data2;
    remainder=data1%data2 ;
    if ((remainder*2)>=data2)
    {
        result++;
    }
    return (result);
}
/*********************************************
*外码计算
*/
void Dis_Weight(void)
{
    ulng Ovcheck;
    ad_dis_calcu();
    AD=ad_lcd1;//保存ad码
    if(ad_lcd>=real_zero)
    {
        Ovcheck=ad_lcd-real_zero;
    }
    else
    {
        Ovcheck=real_zero-ad_lcd;
    }
    if(Ovcheck<=((Maxval/Inteval)*10+90))
    {
        Isol=0;
    }
    else
    {
        Isol=1;
    }
    ad_lcd1=RoundOff(ad_lcd1,10);
    ad_lcd1 = ad_lcd1 * Inteval;
    if(ad_lcd1==0)
    {
        ad_nag_flag=0;
    }
    if (ad_lcd1<=Inteval*3)
    {
        nag=0;
    }
    if (ad_lcd1<=20*Inteval)
    {
        ZeroPass=0;
    }
}

/***************************************
*皮重计算
*/
void ad_dis_calcu(void)
{
    if(ad_lcd>=ad_tare)
    {
        ad_nag_flag=0;
        nag=0;
        ad_lcd1=ad_lcd-ad_tare;
    }
    else
    {
        ad_nag_flag=1;
        nag=1;
        ad_lcd1=ad_tare-ad_lcd;
    }

    if(ad_tare>=real_zero)
    {
        if((ad_tare-real_zero)<5)
        {
            IsTare=0;
        }
        else
        {
            IsTare=1;
        }
    }
    else
    {
        if((real_zero-ad_tare)<5)
        {
            IsTare=0;
        }
        else
        {
            IsTare=1;
        }
    }
}
/*********************************************
 Description:
 Argument   :
 Return     :
**********************************************/
void Do()
{
    if(IsStb)
    {
        Check_Not_Wen();
        Zero_Trace();
        ad_lcd = ad_read;
    }
    else
    {
        Check_Wen();
        ad_lcd = ad_read;
    }
    CheckZero(ad_read);
    ad_last=ad_read;
}
/*********************************************/


/******************************
*置零处理
*/
void Zero_Pro(void)
{
    //ulng Start_w;

    if(stas_s0==0)
    {

        //Start_w=((Maxval/(ulng)Inteval)*5)/10;//5%

        //if ((IsStb)&&(ad_lcd<=(ad_start+Start_w))&&(ad_lcd>=(ad_start-Start_w))&&(!IsTare))
        if ((IsStb)&&(!IsTare))
        {
            ad_tare=ad_tare+(ad_lcd-real_zero);
            real_zero=ad_lcd;
            Zero_Save();
        }
        return;
    }
}
/***************************
*最大去皮量计算
*/
ulng maxtare(void)
{
    return(Maxval-Inteval);
}
/***************************
*去皮处理
*/
void Tare_Pro(void)
{
    if ((IsStb)&&(stas_s0==0))
    {
        if ((ad_lcd>=real_zero) && ((ad_lcd-real_zero)<=((maxtare()/Inteval)*10)))
        {
            ad_tare = ad_lcd;
        }
    }
    if ((IsStb)&&(IsZeroFlag)&&(stas_s0==0))
    {
        ad_tare = ad_lcd;
        real_zero = ad_lcd;
        IsTare = 0;
    }
    if ((IsStb)&&(IsTare)&&(ad_lcd<real_zero)&&(stas_s0==0))
    {
        ad_tare = real_zero;
    }
}
/*************************************************/
/******************************
*置零处理
*/
void Zero_Pro1(void)
{
    ulng Start_w;

    if(stas_s0==0)
    {
        Start_w=((Maxval/(ulng)Inteval)*5)/10;//5%

        if ((IsStb)&&(ad_lcd<=(ad_start+Start_w))&&(ad_lcd>=(ad_start-Start_w))&&(!IsTare))
        {
            ad_tare=ad_tare+(ad_lcd-real_zero);
            real_zero=ad_lcd;
            Zero_Save();
        }
        return;
    }
}

/***********************************
*重量标定计算
*/
void fullcalculate(void)
{
    float SpanFull=0;
    float spanz1=0;
    SpanFull=((float)keyword/(float)Inteval*10);
    spanz1=SpanFull;
    spanz=(spanz1/((float)ad_sample-(float)ad_zero));
    ad_read=adcalculate(ad_zero);				//建立零点
    ad_last=ad_read;
    ad_lcd= ad_read;
    ad_start=ad_read;
    ad_tare=ad_read;
    real_zero=ad_read;
    f_zeroset=1;
}
/******************************************
*标定零位计算
*/
void zerocalculate(void)
{
    ad_zero=ad_sample;
}
/***********************************
*AD值计算
*/
ulng adcalculate(__IO ulng ads)
{
    float adcal=0;
    adcal=(float)ads-((float)ad_zero-((float)ZERO/spanz)); // ZERO=500000; ad_zero=500000; spanz=1。2010-01-24
    adcal=adcal*spanz;
    return((ulng)(adcal+0.5));
}
/***************************************/


/*************************************
*滤波函数
*输入：采样值x
*输出：返回滤波后的结果值
*/
ulng EX_QR_Filter(ulng x)
{
    uchar i;
    if(ad_ini_flag==0)
    {
        for(i=0; i<4; i++)
        {
            Avad[i]=x;
            Bvad[i]=x;
            Cvad[i]=x;
            Dvad[i]=x;
            Evad[i]=x;
            Fvad[i]=x;
            Gvad[i]=x;
            Hvad[i]=x;
            Ivad[i]=x;
            Jvad[i]=x;
        }
        ad_ini_flag=1;
        return(x);
    }
    else
    {
        Ad_tol+=x;
        Ad_cnt++;
        if(Ad_cnt>=AVG_CNT)
        {
            Avad[3]=Avad[2];
            Avad[2]=Avad[1];
            Avad[1]=Avad[0];
            Avad[0]=Ad_tol/AVG_CNT;
            Ad_cnt=0;
            Ad_tol=0;
        }
        else
        {
            return((ulng)(AD_result+0.5f));
        }
    }

    Bvad[3]=Bvad[2];
    Bvad[2]=Bvad[1];
    Bvad[1]=Bvad[0];
    Bvad[0]=0.1f*Avad[0]+0.2f*Avad[1]+0.3f*Avad[2]+0.4f*Avad[3];

    Cvad[3]=Cvad[2];
    Cvad[2]=Cvad[1];
    Cvad[1]=Cvad[0];
    Cvad[0]=0.1f*Bvad[0]+0.2f*Bvad[1]+0.3f*Bvad[2]+0.4f*Bvad[3];

    Dvad[3]=Dvad[2];
    Dvad[2]=Dvad[1];
    Dvad[1]=Dvad[0];
    Dvad[0]=0.1f*Cvad[0]+0.2f*Cvad[1]+0.3f*Cvad[2]+0.4f*Cvad[3];

    Evad[3]=Evad[2];
    Evad[2]=Evad[1];
    Evad[1]=Evad[0];
    Evad[0]=0.1f*Dvad[0]+0.2f*Dvad[1]+0.3f*Dvad[2]+0.4f*Dvad[3];

    Fvad[3]=Fvad[2];
    Fvad[2]=Fvad[1];
    Fvad[1]=Fvad[0];
    Fvad[0]=0.1f*Evad[0]+0.2f*Evad[1]+0.3f*Evad[2]+0.4f*Evad[3];

    if (fs[1]==0)
        AD_result=Avad[0];
    else if (fs[1]==1)
        AD_result=Avad[0];
    else if (fs[1]==2)
        AD_result=Avad[0];
    else if (fs[1]==3)
        AD_result=Avad[0];
    else if (fs[1]==4)
        AD_result=Avad[0];
    else if (fs[1]==5)
        AD_result=Bvad[0];
    else if (fs[1]==6)
        AD_result=Cvad[0];
    else
        AD_result=Dvad[0];

    return((ulng)(AD_result+0.5f));
}

/****************************************************
*	这是一个延迟函数
*/
void Delay(__IO uint32_t nCount)
{
    /* __IO 就是volatile, 加上这个后可以避免延迟函数被编译器优化掉 */
    for(; nCount != 0; nCount--);
}
/********************************************************/

