我们从2011年坚守至今,只想做存粹的技术论坛。  由于网站在外面,点击附件后要很长世间才弹出下载,请耐心等待,勿重复点击不要用Edge和IE浏览器下载,否则提示不安全下载不了

 找回密码
 立即注册
搜索
查看: 1614|回复: 1

上位机波形检测C++

[复制链接]

该用户从未签到

1

主题

0

回帖

0

积分

一级逆天

积分
0

终身成就奖

QQ
发表于 2017-11-26 09:51:12 | 显示全部楼层 |阅读模式
//--------------------------------------------------------------------
-----------------------------------------------------------------------------------

#include<c8051f020.h>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include "subSecondyuan.c"

//#include"advancesubroutine.c"

#define     PARTICLENUM   6
#define     PeakCountNUM  25
#define     UARTVIBRA   0xfe                  // 连续振动
#define     UARTSHOCK    0xfd                // 手动冲击
#define     UARTSCAN    0xfc                // 扫频振动
#define     VIBRASTOP   0xfb                // 连续振动停止
#define     SHOCKSTOP   0xfa                 // 手动冲击停止
#define     SCANSTOP    0xf9                // 扫频振动停止
#define     MANSHOCK    0xf8                  // 执行一次手动冲击
#define     RUNPROGRAM    0xf7                // 全速运行方案
#define     SENDPROGRAM 0xf6                   // 接收上位机发送的方案
#define     RUNPROGRAMSTOP     0xf5            // 全速运行停止
#define        NOPROGRAM        0xf2                 // 方案中没有指令
#define     READPROGRAM     0xf1            // 上位机读取方案
#define        ENABLESAMPLE     0xef             // 允许采集振动加速度
#define     UARTVIBRAZERO   0xed            // 振动通道零位校准
#define        QUICKRUNEND        0xee               // 全速运行结束
#define     UARTVIBRAZEROS  0xec            // 振动通道零位校准停止
#define     UARTVIBRAGAIN   0xeb            // 振动通道增益校准
#define     UARTVIBRAGAINS  0xea            // 振动通道增益校准停止   
#define     UARTVIBRAACCE   0xe9            // 振动加速度校准
#define     UARTVIBRAACCES  0xe8            // 振动加速度校准停止
#define     UARTSHOCKZERO   0xe7            // 冲击通道零位校准
#define     UARTSHOCKZEROS  0xe6            // 冲击通道零位校准停止
#define     UARTSHOCKGAIN   0xe5            // 冲击通道增益校准
#define     UARTSHOCKGAINS  0xe4            // 冲击通道增益校准停止                  
#define     UARTSHOCKACCE   0xe3            // 冲击加速度校准
#define     UARTSHOCKACCES  0xe2            // 冲击加速度校准停止
#define        STARTRUN        0xe1            // 下位机开始运行
#define        QUICKRUNARBOR    0xdf            // 快速运行中止
#define        ANALYSERESULT    0xdd            // 分析结果
#define        RUNDEFAULTPROGRAM    0xdc        // 运行默认程序   
#define     REQUESTACCE     0xdb            // 上位机请求加速度
#define     SETPARAMETER   0xda            // 上位机设置默认工作台及默认方案号
#define     READPARAMETER  0xd9            // 上位机读入默认工作台及默认方案号
#define     SENDCALCOEFF   0xd8            // 上位机发送校准系数
#define     READCALCOEFF   0xd7            // 上位机读取校准系数
#define     STOPCURSHAKER  0xd6            // 上位机停止当前振动台
#define     CHANGESHAKER   0xd5            // 上位机改变当前工位
#define     SELFCHECK       0xd4            // 自检
#define     REQUESTVIBRAACCE 0xd3            // 请求振动加速度    余加
#define     REQUESTSHOCKACCE 0xd2            // 请求冲击加速度   余加


// 串口状态下的特殊命令字
/*
#define        NOPROGRAM    0xf2                 // 方案中没有指令
#define        MATERLAR    0xf0                 // 马特拉指令
#define        ANALYSEDATA        0xe0              // 通知上位机分析数据     
#define        ANALYSEDISB        0xde            // 禁止分析
*/
#define     NOTHING     0x00
#define     REQUEST     0x01
#define     ACK         0x02
#define     UARTDLE     0x10                  // 起始桢
#define     UARTSTX        0x02
#define     UARTETX     0xff                  // 结束桢
#define        SUCCESS        0x01                // 接收成功
#define     STARTERROR  0x02                   // 起始桢错误        
//#define        NOCOMMAND    0x05                   // 无指令


// 编程状态下特殊命令字,同时也用于区分不同的界面
#define        STX            0xfe                // 表示一个试验程序的开始
#define        VIBRA        0xfd                // 表示此指令将使振动器工作在振动状态
#define        SHOCK        0xfc                // 表示此指令将使振动器工作在冲击状态
// 按键值定义
#define SelectShaker1    0x1e               // 振动台1
#define SelectShaker2    0x17//1d               // 振动台2
#define SelectShaker3    0x1b               // 振动台3
#define SelectAllShaker    0x0f               // 默认工作振动台
#define QStop            0x1d//17               // 下位机快速停止键
/*

#define        SCAN        0xfb
#define        ETX            0xfa                // 表示一个试验程序的结束
#define     VIBRACAL    0xf9
#define        SHOCKCAL    0xf8
#define     VIBRADECCAL 0xf7
#define     SHOCKDECCAL 0xf6
*/
// 转换电压命令字
//#define        ACCEDISP        9.76   
//#define     VIBRAVOLT       18.37             // AD620输出电压转加速度的系数
float     VIBRACALVOLT=    13.46;            //r34=100k,r35=1k;
//#define     VIBRACALVOLT    41.13               //r34=200k,r35=1k;
float     SHOCKCALVOLT=    42.89;
float    ACCEDISP=9.76;
float   VIBRAVOLT=18.37;             // AD620输出电压转加速度的系数   
//FLOAT和uchar共用体         
typedef union _float_uchar_        // 用于将浮点型的加速度转换为4个字节向上位机发送
{
  float float_kind;
  uchar uchar_kind[4];
}float_uchar;
float_uchar fAcceleration;               // 采样的加速度值
uchar CalCoeff4[4];
float   ReceiveCalCoeff[8]={0};         // 保存校准系数
//float   ReceiveCalCoeff1[6]={9.76,18.37,9.76,18.37,9.76,18.37};         // 保存校准系数
volatile uchar    ucTotalInst[TotalProgram] ={0};// 用于存储相应方案中已经编辑的指令总数
volatile uchar    DefaultProgrNum[3] = {1,1,1};                 //    存储每个振动台的默认方案号
volatile uchar   DefaultShaker[3] = {1,1,1};                 //  存储默认工作的振动台
uchar   TimeBetweenProg[2]={1,1};                        //  存储方案运行时的时间间隔
uint pdata    TimeBetwProgCount;                             //  对TIMER1进行计数,用于记录方案运行时的时间间隔
volatile uchar    ucProgramNum=0;                        // 编程状态下表征试验方案的序号
uchar   ucShakerNum=1;                        // 振动台号
volatile uchar     ucReceiveData[80]={0};                    // 该数组用于保存接收串口的数据
volatile uchar     ucSendData[80]={0};                        // 该数组用于保存发送串口的数据
uchar     ucCountRece;                        // 改变量用于计算接收串口数据的字节数
volatile uchar     bReceEndFlag=0;                        // 串口接收数据结束标志位,为真表示数据接收结束
volatile uchar    ucPeakCount=0;                         // 表示采集的正弦加速度的周期数,每次采集完成一个周期加1
volatile uchar     bPeakCountFlag=0;
volatile float     shockacceprog = 0;
volatile uchar  CalcShockAcceFlag = 0;                // 计算冲击加速度标志位,用于在运行过程中计算最后一次冲击的加速度,并发送至上位机显示,余加
uchar    ucReceState;                         // 表示串口接收或发送的状态
uchar   ucReadCommand[48];                    // 从e2prom中读取指令
uchar     ucSendInstruction[64] =
{
0x02,0x03,0x04,0x18,0x24,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18,0x00,0x00,      // 0----0  
0x00,0x00,0x00,0x10,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x7C,0x00,0x00,      // 1----1
0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x04,0x04,0x08,0x10,0x20,0x42,0x7E,0x00,0x00,      // 2----2
0x00,0x00,0x00,0x3C,0x42,0x42,0x04,0x18,0x04,0x02,0x02,0x42,0x44,0x38,0x00,0x00     // 3----3
};    // 发送的程序指令
#define EAABLEADC1C TMR3RL = -(SYSCLK/(SAMPLERATE1/10));ADC1CN |= 0x80              // 设置ADC1的采样老率为10k,用于校准冲击加速度的前向通道
#define DISABLEADC1 ADC1CN &= 0x7f;    TMR3RL = -(SYSCLK/SAMPLERATE0)                  // 禁止ADC1,将采样率设置为ADC0的采样率

#define ENABLEADC1  TMR3RL = -(SYSCLK/SAMPLERATE2); ADC1CN |= 0x80                    // 设置ADC1的采样率为40k,使能ADC1,用于测量冲击加速度

#define ENABLEDETLED    P4 = P4|0x50     //      P4 = P4|0x50
#define DISABLEDETLED   P4 = P4&0xbf     //      P4 = P4&0xbf
#define ENABLEFAILLED1  P4 = P4|0x30     //      P4 = P4|0x30
#define DISABLEFAILLED1 P4 = P4&0xdf     //      P4 = P4&0xdf
#define ENABLEFAILLED2  P5 = P5|0x20
#define DISABLEFAILLED2 P5 = P5&0xdf
#define ENABLEFAILLED3  P5 = P5|0x40
#define DISABLEFAILLED3 P5 = P5&0xbf
#define DISABLEFAILLEDAll  P5 = P5&0xbf; P5 = P5&0xdf4 = P4&0xbf

sbit    Relay2            = P3^5;                // 液晶写选中
sbit    Relay1            = P3^7;                // 245读选中


//---------------------------------------------------------------------------------------
// 主函数
//---------------------------------------------------------------------------------------
void main(void)
{
    WDTCN = 0xde;                           // 禁止看门狗定时器
    WDTCN = 0xad;
   

    Resource_Init();                        // 对使用的各种单片机内部资源初始化
    ReadTotalInst();                           // 读入方案中包含的指令数,如果该方案没有编辑指令,指令数为1
//    longDELAY(400);                             // 延时一段时间,等待电荷放大器稳定
//    ucKeyNum=0x07;
//    bKeyDown=1;
    while(1)
    {
        //if(bShockCommand && ucShockTimesBuffer==1)
        //{
        //    ET0=0;
        //    SampleShockAcceProg();
        //    ET0=1;
        //}
//           if(bQuickRunFlag)                 //     全速运行执行相应的方案
//        {
    /*        if(Particle==0&&bShockCommand==0)      // 检测到微粒且并没有执行冲击指令,说明器件中含有多余物。
            {
                if(ucParticleNum&gtARTICLENUM)    // 如果微粒碰撞的次数超过一定值,说明多余物较明显,点亮失效指示灯。
                {
                    ENABLEFAILLED;
                    bIsParticleFlag = TRUE;         // 说明检测到多余物
                }
            }
            */            
//        }
        Key();   // 键盘服务程序
        if(Particle==0&&bShockCommand==0)  
        {
            ENABLEDETLED;                    // 如果检测到噪声超限且当前并没有执行冲击指令,点亮噪声超限指示灯
            ucParticleNum++;                // 次数加1
        }
        else    DISABLEDETLED;
        /*if(CommandType==0x01)                 //     全速运行执行相应的方案
        {
            if(Particle==0&&bShockCommand==0)      // 检测到微粒且并没有执行冲击指令,说明器件中含有多余物。
            {
                if(ucParticleNum&gtARTICLENUM)    // 如果微粒碰撞的次数超过一定值,说明多余物较明显,点亮失效指示灯。
                {
                    EnableFailLed(ImpactPara.ShakerNum);
                //    bIsParticleFlag = TRUE;         // 说明检测到多余物
                }
            }
        } */               
        if(ucPeakCount>=PeakCountNUM)         // 如果已经采集25个周期,求平均值并在液晶上显示
        {
            EA = 0;
            ucPeakCount=0;
            CalculSampleAcce();
            nSandFrenq++;
            if(nSandFrenq>=5)nSandFrenq=0;
            if((bExuteVibra == 1)&&(nSandFrenq==0))
            {
                fAcceleration.float_kind=PeakAverage()*VIBRAVOLT;
                 ucUsartSampleAcce=REQUESTVIBRAACCE;
                 SendUartAcce(ucUsartSampleAcce);   
            }   
               
            EA = 1;
        }  
         if(bScanEndFlag)
        {
            bScanEndFlag=0;
            Usart_ScanParaStop();
        }
        if(bReceEndFlag==1)                    // 不为0,说明接收到了数据,对接收数据进行处理
        {
            bReceEndFlag = 0;                // 接收数据标志位清0                                                                                                                                                                                                                  
            IE &= 0xEF;                        // 关闭串口中断,防止数据处理过程中再次发生串口中断
        //    TR0 = 0;
            ProcessData();                    // 处理接收的串口数据
            ucCountRece = 0;                // 接收的串口数据计数变量清0 ,为下次接收串口数据准备
            RI0=0;
        //    TR0 = 1;
            IE |= 0x10;                        // 重新开串口中断
        }  
        if(ShakerRunProgFlag)
        {
            ShakerRunProgFlag=0;
            if(0==RunShakerNumFlag)
            {
                   if(0==DefaultShaker[0])    RunShakerNumFlag=1;
                else  
                {
                    ucProgramNum=DefaultProgrNum[0];
                    ImpactPara.ShakerNum=1;
                    Usart_RunProgram();
                }                     
            }
            if(1==RunShakerNumFlag)
            {
                   if(0==DefaultShaker[1])    RunShakerNumFlag=2;
                else
                {
                     ucProgramNum=DefaultProgrNum[1];
                     ImpactPara.ShakerNum=2;
                     Usart_RunProgram();
                }            
            }
            if(2==RunShakerNumFlag)
            {
                   if(0==DefaultShaker[2])    RunShakerNumFlag=0;
                else
                {
                     ucProgramNum=DefaultProgrNum[2];
                    ImpactPara.ShakerNum=3;
                    Usart_RunProgram();
                }            
            }
                    
        }
        if(CalcShockAcceFlag)        // 测量冲击加速度余加
        {
            CalcShockAcceFlag = 0;
            SHOCKPARASET
            ACCEDISP=ReceiveCalCoeff[2*(ImpactPara.ShakerNum-1)];     // 冲击加速度值与电压值之间的转换系数
            fAcceleration.float_kind = SampleRunShockAcce();                               // 计算冲击加速度
            SendUartAcce(REQUESTSHOCKACCE);             // 发送冲击加速度
        
        }      
        if(bExecuteFlag)                //方案运行结束后处理结果
        {
            ExecuteInstEnd();
            RunShakerNumFlag++;
            RunShakerNumToll--;          //运行的振动台数目减1
            if(RunShakerNumToll!=0)
            {   
                TR1=1;
                ET1 =1;                // 开T1中断
            }
            else                    // 默认工作振动台运行结束
            {
                RunShakerNumFlag=0;      
                longDELAY(10);
                 SendSampleVibra(QUICKRUNEND);     // 通知上位机方案运行结束
                 bComputerRunFlag=0;            // 上位机控制振动台动作结束,下位机可以操作按键控制振动台工作
                CommandType=0;             // 全速运行方案停止
            }
                                                                                                                                             
        }
    }     
}
//---------------------------------------------------------------------------------------
// 此函数在上电初始化时被调用
// 用于读取各个已编辑的方案的指令/振动台的默认方案/默认工作的振动台/方案运行的时间间隔
//
//---------------------------------------------------------------------------------------

//---------------------------------------------------------------------------------------
// 键盘应用子程序
//---------------------------------------------------------------------------------------
void Key(void)                                   
{   
//    uchar tempShaker;
    uchar SkakerFlag;
    if(bKeyUp&&bKeyDown)                      // 有键按下执行键盘服务程序
    {
    //    ImpactPara.ShakerNum=0;
        SkakerFlag=0;
        bKeyDown = FALSE;
        if(0==bComputerRunFlag)            // 上位机控制振动台动作结束,下位机可以操作按键控制振动台工作
        {
            switch(ucKeyNum)
            {
                case SelectShaker1:   
                     if(CommandType==0x01)    return;                // 振动台正在执行方案
                     SkakerFlag=1;
                     ImpactPara.ShakerNum=1;
                     RunShakerNumFlag=0;
                break;
                case SelectShaker2:
                     if(CommandType==0x01)    return;                // 振动台正在执行方案
                     SkakerFlag=1;
                     ImpactPara.ShakerNum=2;
                     RunShakerNumFlag=1;
                break;
                case SelectShaker3:
                     if(CommandType==0x01)    return;                // 振动台正在执行方案
                     SkakerFlag=1;
                     ImpactPara.ShakerNum=3;
                     RunShakerNumFlag=2;
                break;   
                case SelectAllShaker:                        // 全速运行   
                     if(CommandType==0x01)    return;                // 振动台正在执行方案
                     CommandType=1;             //     全速运行执行相应的方案        
                     RunShakerNumFlag=0;            
                      RunShakerNumToll=DefaultShaker[0]+DefaultShaker[1]+DefaultShaker[2];  // 记录默认工作振动台数目
                     DISABLEFAILLEDAll;                  // 失效指示灯熄灭
                     SendSampleVibra(STARTRUN);
                     longDELAY(100);
                      ShakerRunProgFlag=1;                                // 启动运行方案   
                     return;
                break;
                case QStop:   
                     if(CommandType==0x00)    return;                // 振动台正在执行方案
                     CommandType=0;             // 全速运行方案停止
                     TimeBetwProgCount=0;    // 两个连续运行的方案之间的时间间隔,对timer1计数
                      ShakerRunProgFlag=0;    // 振动台正在运行方案标志位
                      RunShakerNumToll=0;
                     RunShakerNumFlag=0;               
                     Usart_RunProgramStop();
                     SendSampleVibra(QUICKRUNARBOR);        // 中止运行程序
                     return;
                break;
                default:
                break;
            }
            if(SkakerFlag)
            {
            //    tempShaker=    DefaultShaker[ImpactPara.ShakerNum-1];
                if(DefaultShaker[ImpactPara.ShakerNum-1])
                {
                    DISABLEFAILLEDAll;                  // 失效指示灯熄灭
                    RunShakerNumToll=1;
                    SendSampleVibra(STARTRUN);
                    longDELAY(100);
                       ShakerRunProgFlag=1;
                    CommandType=1;             //     全速运行执行相应的方案
                }
                else
                {
                       SendSampleVibra(NOPROGRAM);        // 没有方案
                }
            }
        }
    }
}
//--------------------------------------------------------------------------------------
// 选择相应的失效指示灯
//--------------------------------------------------------------------------------------
void SlectShaker(uchar Num)       // 选择相应的失效指示灯
{
    uchar temp;
    temp=Num;
    switch(temp)
    {
        case  1:
            Relay1=0;
            Relay2=0;
            DISABLEFAILLED1;
        //    EnableShaker1;
        break;
        case 2:
            Relay1=1;
            Relay2=0;
            DISABLEFAILLED2;
        break;
        case 3:
            Relay1=0;
            Relay2=1;
            DISABLEFAILLED3;
        break;
        default:
            Relay1=0;
            Relay2=0;
        break;
    }
    longDELAY(10); //短延时,避免继电器切换时,点亮指示灯
}
//--------------------------------------------------------------------------------------
// 点亮相应的失效指示灯
//--------------------------------------------------------------------------------------
void EnableFailLed(uchar Num)       // 点亮相应的失效指示灯
{
    uchar temp;
    temp=Num;
    switch(temp)
    {
        case  1:
             ENABLEFAILLED1;
        break;
        case 2:
              ENABLEFAILLED2;
        break;
        case 3:
              ENABLEFAILLED3;
        break;
        default:         
        break;
    }
}
//--------------------------------------------------------------------------------------
// 熄灭相应的失效指示灯
//--------------------------------------------------------------------------------------
void DisableFailLed(uchar Num)       // 熄灭相应的失效指示灯
{
    uchar temp;
    temp=Num;
    switch(temp)
    {
        case  1:
             DISABLEFAILLED1;
        break;
        case 2:
              DISABLEFAILLED2;
        break;
        case 3:
              DISABLEFAILLED3;
        break;
        default:         
        break;
    }
}
void ReadTotalInst(void)
{
    uint buffer;  
    uchar i,j;
    ET0 = 0;
    SM_Receive (AT24C256N1,TotleInstrucADD,ucTotalInst,TotalProgram);      //  读入每个方案的指令总数并将结果存在ucTotalInst数组中
    SM_Receive (AT24C256N1,DefaultProgrNumADD,DefaultProgrNum,3);          //  读入每个振动台的默认方案
    SM_Receive (AT24C256N1,DefaultShakerADD,DefaultShaker,3);              //  读入默认工作的振动台
    SM_Receive (AT24C256N1,TimeBetweenProgADD,TimeBetweenProg,2);          //  读入默认工作的振动台
    for(i=0;i<8;i++)
    {     
    buffer=CalCoeffADD+i*4;
    /*
        fAcceleration.float_kind = ReceiveCalCoeff1;   
        for(j=0;j<4;j++)      CalCoeff4[j]=fAcceleration.uchar_kind[j];
        SM_Send (AT24C256N1,buffer,CalCoeff4,4);      //  读入校准系数
    */        
        SM_Receive (AT24C256N1,buffer,CalCoeff4,4);      //  读入校准系数
        for(j=0;j<4;j++)      fAcceleration.uchar_kind[j]=CalCoeff4[j];
         ReceiveCalCoeff= fAcceleration.float_kind ;        
    }  
    SHOCKCALVOLT =     ReceiveCalCoeff[6];   
    VIBRACALVOLT =     ReceiveCalCoeff[7];
    ET0 = 1;
}
//------------------------------------------------------------------------------------------
// 扫描查询,每20ms定时器产生一个中断,中断程序查询是否有键按下,且具有去抖动功能
//------------------------------------------------------------------------------------------
void TIMER0(void) interrupt 1               // 键盘扫描中断程序
{
    uchar press=0x00;   
   
    TH0=-(40960/256);                         // 重新赋初值
       TL0=-(40960%256);

    bKeyUp = TRUE;
    press= KEYINPUT;
    KEYINPUT=(KEYINPUT|0x1f);              // 配置P5.0-P5.4为输入管脚
   
    press=press&0x1f;
    if(press!=0x1f)              // 判断是否有键按下
    {
           bKeyDown = TRUE;    // 有键按下
        bKeyUp=FALSE;
        ucKeyNum=press;
    }
}
//--------------------------------------------------------------------
// 中断服务程序,Smbus的的中断服务程序。用于和外部I2C存储器通讯
//--------------------------------------------------------------------
void SMBUS_ISR (void) interrupt 7            // 当SMBus状态改变时,进入
{
    switch (SMB0STA)                        // SMBus状态码SMB0STA寄存器
    {                     
        case SMB_START:                        // 主发送器或接收器起始条件已发送
                                            // 在该状态发送的COMMAND字的R/W位总是为0(W)
                                            // 因为对于读和写操作来说都必须先写存储器地址
            SMB0DAT = (Command & 0xFE);     // 装入要访问的从器件的地址
            STA = 0;                         // 手动清除START位
        break;
        // 发送器/接收器重复起始条件已发送,该状态只应在读操作期间出现在存储器地址已发送并得到确认之后
        case SMB_RP_START:
            SMB0DAT = Command;                 // COMMAND中应保持从地址+ R.
            STA = 0;
        break;
        // 主发送器从地址+ WRITE已发送收到ACK
        case SMB_MTADDACK:
            SMB0DAT = AddressT[0];                 // 装入待写存储器地址的高8位
            Add_HorL_Flag=1;                    // 为下一次发送低8位做准备
        break;
        // 主发送器从地址+ WRITE已发送收到NACK ,从器件不应答发送STOP + START重试
        case SMB_MTADDNACK:
            STO = 1;
            STA = 1;
        break;
        // 主发送器数据字节已发送收到ACK
        // 该状态在写和读操作中都要用到,如果Address已发送,检查COMMAND中的R/W 值以决定下一状态
        case SMB_MTDBACK:
            if(Add_HorL_Flag)
            {
                   SMB0DAT = AddressT[1];                 // 装入待写存储器地址的低8位
                Add_HorL_Flag=0;
               
            }
            else
            {
                if(ByteNumber!=0)
                {
                    if (Command & 0x01)         // 如果R/W=READ,则表示读指令,发送重复起始条件
                    {
                        STA = 1;                // 发送重复起始条件
                    }
                    else
                    {
                        SMB0DAT = *PByte;       // 发送当前字节
                        PByte++;                 // 指向下一个待发送的字节
                        ByteNumber--;
                    }
                }
                else                            // 如果BYTE_NUMBER=0,所有数据发送完成,传输结束
                {
                    STO = 1;                     // 发送一个停止条件
                    SMBusy = 0;                    // 释放SMBus
                }
                    
            }            
        break;
        // 主发送器数据字节已发送收到NACK 从器件不应答发送STOP + START重试
        case SMB_MTDBNACK:
            STO = 1;
            STA = 1;
        break;
        // 主发送器竞争失败 不应出现如果出现重新开始传输过程
        case SMB_MTARBLOST:
            STO = 1;
            STA = 1;
        break;
        //主接收器从地址+ READ 已发送收到ACK 设置为在下一次传输后发送NACK因为那将是最后一个字节(唯一)
        case SMB_MRADDACK:
               if(ByteNumber==1)                // 如果只读一个字节,则说明下一个接收数据是最后一字节(唯一)
            {
                AA = 0;                     // 在应答周期发送NACK,表示下次接收数据后发送NACK
            }
        break;
        // 主接收器从地址+ READ 已发送收到NACK,从器件不应答发送重复起始条件重试
        case SMB_MRADDNACK:
            STA = 1;
        break;
        //收到数据字节ACK已发送,该状态不应出现因为AA已在前一状态被清0如果出现发送停止条件
        case SMB_MRDBACK:                    
            *PByte=SMB0DAT ;          // 将接收数据存入接收缓冲区
            if(ByteNumber==2)          // 剩下一个字节未读,设置应答周期发送NACK
            {
                AA = 0;
            }
            PByte++;                  // 指向接收缓冲区
            ByteNumber--;            // 接收一个字节,变量减1,表示剩下的未读字节数
        break;
        // 收到数据字节NACK已发送, 读操作已完成读数据寄存器后发送停止条件
        case SMB_MRDBNACK:
            *PByte = SMB0DAT; // 将最后一个字节存入接收缓冲区
            STO = 1;                        // 发送一个停止条件,表示读过程已完成
            SMBusy = 0;                     // 释放SMBus
        break;
        // 在本应用中所有其它状态码没有意义通信复位
        default:
        STO = 1;                             // 通信复位
        SMBusy = 0;
        break;
    }
    SI = 0;                                    // 清中断标志位
}

//---------------------------------------------------------------------------------------
// 串口中断,用于上位机和下位机的互相通讯
//---------------------------------------------------------------------------------------
void receive(void) interrupt 4              //  串口中断
{
    if(RI0)
    {        
        RI0=0;
        bStopShockCal=0;             //我加的
        ucReceiveData[ucCountRece] = SBUF0;   
        ucCountRece++;   
        if(ucCountRece>1)
        {
            if((ucReceiveData[ucCountRece-2]==UARTDLE)&&(ucReceiveData[ucCountRece-1]==UARTETX))// 判断是否收到数据包的结束桢
            {               
                bReceEndFlag = 1;
            }                          
        }
      }                    
}
//---------------------------------------------------------------------------------------
// ADC0中断服务程序 ADC0转换结束中断服务程序,计算采集的振动加速度的有效值
//---------------------------------------------------------------------------------------
void ADC0_ISR (void) interrupt 15
{
    int WaveBuffer;
    int buffer;
    AD0INT = 0;                                 // ADC转换结束清除标志
    WaveBuffer = ADC0;
    nWaveCount++;
    fSampleValue = (float) WaveBuffer*2.462/4096.0+0.023;///fCoefficient;// 系数由来 2.4/2048/sqrt(200)*系数  
    fVirtualValue = fVirtualValue + fSampleValue;//求取平均值   
     if(bGainCalFlag==TRUE||bZeroCalFlag==TRUE)                  // 工作在振动校准状态
    {     
          if(nWaveCount==ucSampleNumber)
        {
                nWaveCount = 0;
            fVirtualValue = fVirtualValue/ucSampleNumber;
           fVirtualBuffer[ucPeakCount] = fVirtualValue;                         // 记录该有效值,为显示做准备
            fVirtualValue = 0;
            ucPeakCount++;
        }
        return;
    }
    if(nWaveCount==ucSampleNumber)             // 一个采样周期结束
    {
        nWaveCount = 0;
        AD0EN = 0;
        //fVirtualValue = sqrt(fVirtualValue);// 计算该周期内采集加速度的有效值
        fVirtualValue = fVirtualValue/ucSampleNumber;  //计算该周期内采集加速度的平均值
               
        fError = fInput-fVirtualValue;
        if(bLoopFlag==OPENLOOP)                    // 如果是开环控制,则强行将误差设置为0,即禁止闭环控制功能
        {
            fError = 0;
        }
        if(fabs(fError)>=0.002)                   // 根据误差调节给定,实现闭环控制   
        {
            buffer = DAC1;

    //        if (ucSampleNumber>=200)
    //            buffer = buffer+(uint)50*fError; //系数为4095/VVREFD*p调节系数 p=3.32  500
    //        else if (ucSampleNumber<200&&ucSampleNumber>=100)  
    //            buffer = buffer+(uint)160*fError; //系数为4095/VVREFD*p调节系数 p=3.32  500
    //        else
            buffer =buffer+(uint)100*fError; //系数为4095/VVREFD*p调节系数 p=3.32  500
            if(buffer>=0&&buffer<4000)
            {
                //这段代码改动,原因是da1不好使了,用da0代替之         2008.3.11
                DAC1L = buffer%256;
                DAC1H = buffer/256;
            }
        

        }        
        fVirtualBuffer[ucPeakCount] = fVirtualValue;                             // 记录该有效值,为显示做准备
        fVirtualValue = 0;
        ucPeakCount++;   
        AD0EN = 1;        
    }   
}

//-----------------------------------------------------------------------------
// ADC1中断服务程序 ADC1转换结束中断服务程序用于完成冲击加速度前向通道的零位校
// 准和通道校准、振动加速度、冲击加速度的自动校准,及测量冲击加速度
//-----------------------------------------------------------------------------
void ADC1_ISR (void) interrupt 17
{                                                   
    int WaveBuffer;

    ADC1CN &= 0xdf;                             // 清除ADC1转换结束标志   

    if(bGainCalFlag==TRUE||bZeroCalFlag==TRUE)     // 冲击加速度前向通道校准,即峰值保持电路放大倍数校准            
    {
        WaveBuffer = ADC1;
        nWaveCount++;
        fSampleValue = (float) WaveBuffer/fCoefficient;     // 系数由来 2.4/2048/sqrt(200)*系数
        fVirtualValue =  fVirtualValue + fSampleValue;
        if(nWaveCount>=ucSampleNumber)
        {
            nWaveCount = 0;
            fVirtualValue = fVirtualValue/ucSampleNumber;
            fVirtualBuffer[ucPeakCount] = fVirtualValue;     // 记录该有效值,为显示做准备
            fVirtualValue = 0;
            ucPeakCount++;              
        }      
    }
    else                                    //冲击加速度校准
    {
        ucShockVolt[ucSampleShockCount] = ADC1;// 记录采集的冲击加速度值
        ucSampleShockCount++;
        return;
    }
}

//---------------------------------------------------------------------------------------
// 用于振动台工作在扫频方式时定时,中断时间为25ms,扫频的步进时间最小分辨率为1s
//---------------------------------------------------------------------------------------
void TIMR1(void) interrupt 3                           
{   
    uint    Buffer;

    TH1=-(51200/256);                         // 重新赋初值
       TL1=-(51200%256);

    if (UARTSCAN==ucUsartSampleAcce)
    {
        ucScanCount++;
        Buffer = (uint)ScanPara.StepTime*40;
        if(ucScanCount==Buffer)                 // 时间到,则更新当前振动的频率值
        {
            ucScanCount = 0;
            if(ScanPara.Frequency<ScanPara.EndFre)        // 起始频率小于截止频率,则频率按步进时间增加
            {
                ScanPara.Frequency++;            
            }
            else if(ScanPara.Frequency>ScanPara.EndFre)    // 起始频率大于截止频率,则频率按步进时间减
            {
                ScanPara.Frequency--;
            }
            else bScanEndFlag=1;
            AD0EN = 0;
    //        bScanFlag = 1;         
            nWaveCount = 0;
            ucSampleNumber = 10000/ScanPara.Frequency;                      // 根据振动频率计算加速度一个周期的采样点数
        
            //fCoefficient = 853.3*sqrt(ucSampleNumber);                     // 2048/2.4=853.3
            fInput = (float)ScanPara.Volt/10;                               // 为了存储方便,加速度的值为其存储值的十分之一
                              //  fInput = fInput/15.38/1.499;
            fInput = AcceToVolt(fInput);
            AD0EN = 1;
                                                            // 开AD中断,开始对振动加速度进行采集
        }
        return;     
    }
    else
    {
        TimeBetwProgCount++;
        Buffer=(uint)TimeBetweenProg[RunShakerNumFlag-1]*40;
        if(TimeBetwProgCount>=Buffer)                 // 时间到,
        {
            TimeBetwProgCount=0;   
            ShakerRunProgFlag=1;
            TR1=0;                  // 启动定时器
            ET1 =0;                // 关T1中断
        }
    }

}

//---------------------------------------------------------------------------------------
// PCA0中断服务程序,当计数值发生匹配时,产生中断,用于定时,最小单位为20ms.当运行方案时利
// 用该定时完成振动和冲击指令的运行及切换
//---------------------------------------------------------------------------------------
void PCA0_ISR(void) interrupt 9
{   
    uchar buffer;

    AD0EN = 0;
    CCF0 = 0;                                // 比较匹配中断标志位复位
    CR = 0;                                 // PCA0停止计数
    PCA0L = 0x00;                           // 重新赋初值
    PCA0H = 0x00;
//    if(bQuickRunFlag==0)    return;            // 强行停止,立即返回
    switch(ucReadCommand[ucRunCommandPos])
    {
        case VIBRA:                          // 单步执行振动指令            
//            ResetRelay = 1;                    // 峰值保持有效
            Select1 = HIGH;
            Select2 = HIGH;
            PulseSet = HIGH;                   // 由于中断函数中不能重复调用别的函数
            StyleSet = LOW;                    // 这里将stop函数重新写了一遍
            DELAY(1);
            StyleSet = HIGH;
            DAC1 = 0;                          // 不输出任何电压
            bEndFlag = 1;                    // 振动指令运行完毕
            bExuteVibra = 0;                //振动指令执行完成,关闭向上位机发送振动加速度的程序
            break;
        case SHOCK:                          // 单步执行冲击指令   
            if(ucShockTimesBuffer>=1)
            {                                
                StyleSet = HIGH;              // 使振动台工作在冲击状态,同时使计数器清零
                DELAY(5);
                Select1 = HIGH;
                Select2 = LOW;
                PulseSet=LOW;                // 产生下降延,完成一个周期的扫描,形成一次冲击
                DELAY(2);
                PulseSet=HIGH;
                DELAY(2);
            }        
            if(ucShockTimesBuffer==0)
            {               
                SelectAcce = 1;                // 选择冲击加速度
                Select1 = HIGH;
                Select2 = HIGH;
                PulseSet = HIGH;             // 由于中断函数中不能重复调用别的函数
                StyleSet = LOW;              // 这里将stop函数重新写了一遍
                DELAY(1);
                StyleSet = HIGH;
                DAC1 = 0;                    // 不输出任何电压
                ucShockTimesBuffer = ucReadCommand[ucRunCommandPos+3]+1;
                bEndFlag = 1;                // 冲击指令运行完毕
                PreReadShockAcceNum++;               
            }
            if(bEndFlag==0)                       // 冲击指令的冲击次数没有达到,执行下一次冲击动作
            {
                PCA0CPL0 = 6;              // 冲击之间的间隔为120ms
                PCA0CPH0 = 0;        
                SendFrequency(15);
                SetShockDAInput(PreReadShockAcce[PreReadShockAcceNum]);
                CR = 1;
            }
            ucShockTimesBuffer = ucShockTimesBuffer - 1;   
            if(ucShockTimesBuffer==0)                 // 冲击加速度标志位置1,余加
            {                                       
                CalcShockAcceFlag = 1;     
            }
            break;
        default:break;
    }
    if(bEndFlag==1)                               // 振动指令或冲击指令运行完毕,准备执行下一指令
    {
        bEndFlag = 0;        
//        bExecuteFlag = 1;   
        ucRunCommandNumber++;
        if(ucRunCommandNumber==ucTotalInst[ucProgramNum-1])
        {
            bExecuteFlag = 1;
            return;            // 方案运行完毕        
        }
         
        ucRunCommandPos = ucRunCommandNumber*4;
        switch(ucReadCommand[ucRunCommandPos])                             
        {
            case VIBRA:                                                          // 单步执行振动指令               
                if(CR==0)
                {
                    EnableSpeaker = 0;                                            // 使能扬声器
                    SelectAcce = 0;                                                //振动指令执行开始,打开向上位机发送振动加速度的程序
                    bExuteVibra = 1;
                    SendSampleVibra(ENABLESAMPLE);
                                      
                    bShockCommand = 0;                                            // 选择振动加速度
                    buffer = (uint)ucReadCommand[ucRunCommandPos+3]*50;
                    PCA0CPL0 = buffer%256;
                    PCA0CPH0 = buffer/256;
                    nWaveCount = 0;
                    ucPeakCount = 0;
                    ucSampleNumber = 10000/ucReadCommand[ucRunCommandPos+1];
                    fCoefficient = 853.3*sqrt(ucSampleNumber);
                    fInput = (float)ucReadCommand[ucRunCommandPos+2]/10;
                    fInput = AcceToVolt(fInput);
                    Vibration(ucReadCommand[ucRunCommandPos+1],5);                  // 电压任意给个初始值
                    SetVibraInput(ucReadCommand[ucRunCommandPos+1],ucReadCommand[ucRunCommandPos+2]);
                    bLoopFlag = CLOSELOOP;                                                    // 选中闭环控制
                    AD0EN = 1;
                    CR = 1;   
                }               
                break;
            case SHOCK:                      // 下条指令为冲击指令
                if(CR==0)
                {                    
                    bShockCommand = 1;      // 指示当前执行冲击指令
                    SelectAcce = 1;                                                // 选择冲击加速度
                    EnableSpeaker = 1;                                            // 禁止扬声器
                    PCA0CPL0 = 6;                                              // 冲击之间的间隔为200ms
                    PCA0CPH0 = 0;   
                    SendFrequency(15);
                    ucShockTimesBuffer = ucReadCommand[ucRunCommandPos+3];         // 如果读入冲击指令,将冲击次数参数存入缓冲器中
                    SetShockDAInput(PreReadShockAcce[PreReadShockAcceNum]);
                    CR = 1;
                }               
                break;
            default:break;
        }
    }
}

//---------------------------------------------------------------------------------------
// 此程序用于对上位机发出的指令进行处理,根据不同指令类型执行不同的动作
//---------------------------------------------------------------------------------------
void ProcessData(void)
{
    uchar i;
    uchar count_ten = 0;
       int buffer;
//    uchar NumTempPross;

    if((ucReceiveData[0]==UARTDLE)&&(ucReceiveData[1]==UARTSTX))                // 判断是否使电机
    {
/*        for(i=2;i<ucCountRece-2;i++)           // 把有用数据提取出来,主要是滤去两个都是DLE的情况
        {
            if((ucReceiveData==0x10)&&(ucReceiveData[i+1]==0x10))              
            {
                count_ten++;
                for(j=i;j<=ucCountRece-count_ten;j++)
                {
                    ucReceiveData[j] = ucReceiveData[j+1];
                }               
            }
        } */
        ucReceState =  SUCCESS;                  // 数据接收成功
    }
    else                                      // 接收数据起始桢错误
    {
        ucReceState = STARTERROR;
    }
    if(ucReceiveData[3]==REQUESTACCE)
    {
        UsartSampleAcce();
        for(i=0;i<12;i++)
        {
            ucReceiveData = NOTHING;            // 清空接收缓冲区,为下一次接收数据做准备
            ucReceState = 0;                     // 将接受状态清0,为下一次通讯准备
        }
        return;
    }
   
    if((ucReceiveData[2]==REQUEST)&&(ucReceiveData[3]!=READPROGRAM)&&(ucReceiveData[3]!=READCALCOEFF)&&(ucReceiveData[3]!=READPARAMETER)&&(ucReceiveData[3]!=CHANGESHAKER)&&(ucReceiveData[3]!=REQUESTVIBRAACCE)&&(ucReceiveData[3]!=REQUESTSHOCKACCE))            // 如果接收的是询问数据
    {                                                                                     //&&(ucReceiveData[3]!=STOPCURSHAKER)
        SendUartData();                        // 发送应答数据,告知上位机此次通讯是否正常

    }
   
    if(ucReceState!=SUCCESS)                 // 如果数据没有发送成功,返回,不用执行下列语句
    {
        return;                                // 有故障则返回,不执行相应动作
    }
    ucUsartSampleAcce=ucReceiveData[3];     // 记录指令类型用于在向上位机发送加速度
    switch(ucUsartSampleAcce)                // 通过判断接收的第三个数据判断指令类型
    {
        case SELFCHECK:                          //自检
            //if()                    //自检时保证当前下位机没有任何操作
            {
                VIBRAPARASET;
                longDELAY(200);   
                SHOCKPARASET;
                longDELAY(200);   
                VIBDETSETZERO;
                longDELAY(200);   
                VIBDETSETGAIN;
                longDELAY(200);   
                SHOCKDETSETGAIN;
                longDELAY(200);   
                VIBRAVOLINPUT;
                longDELAY(200);   
                RUNPROGRAME;
                longDELAY(200);   
                INISTATE;
                longDELAY(200);   
               
                SendSampleVibra(SELFCHECK);
            }
        break;
        case UARTVIBRAZERO:                 // 振动通道零位校准
             bComputerRunFlag=1;            // 上位机正在控制振动台动作,禁止下位机工作
             bZeroCalFlag=TRUE;
             Usart_VibraDetectorCal();         
        break;
        case UARTVIBRAZEROS:                // 振动通道零位校准停止                  
             Usart_VibraDetectorCalStop();
             bComputerRunFlag=0;            // 上位机控制振动台动作结束,下位机可以操作按键控制振动台工作   
        break;
        case UARTVIBRAGAIN:                    // 振动通道增益校准
             bComputerRunFlag=1;            // 上位机正在控制振动台动作,禁止下位机工作
             bGainCalFlag=TRUE;
             Usart_VibraDetectorCal();
         break;
        case UARTVIBRAGAINS:                // 振动通道增益校准停止                 
             Usart_VibraDetectorCalStop();
             bComputerRunFlag=0;            // 上位机控制振动台动作结束,下位机可以操作按键控制振动台工作
         break;
        case UARTSHOCKZERO:                 // 冲击通道零位校准
             bComputerRunFlag=1;            // 上位机正在控制振动台动作,禁止下位机工作
              bZeroCalFlag=TRUE;
             bGainCalFlag=FALSE;            // 余加
             Usart_ShockDetectorCal();     
        break;
        case UARTSHOCKZEROS:                 // 冲击通道零位校准停止            
              Usart_ShockDetectorCalStop();  
             bComputerRunFlag=0;            // 上位机控制振动台动作结束,下位机可以操作按键控制振动台工作            
        break;
        case UARTSHOCKGAIN:                 // 冲击通道增益校准
             bComputerRunFlag=1;            // 上位机正在控制振动台动作,禁止下位机工作
               bGainCalFlag=TRUE;
             bZeroCalFlag=FALSE;            // 余加
             Usart_ShockDetectorCal();
        break;
        case UARTSHOCKGAINS:                 // 冲击通道增益校准停止               
             Usart_ShockDetectorCalStop();     
             bComputerRunFlag=0;            // 上位机控制振动台动作结束,下位机可以操作按键控制振动台工作                          
        break;
        case UARTSHOCKACCE:                      // 冲击加速度校准
             bComputerRunFlag=1;            // 上位机正在控制振动台动作,禁止下位机工作    ,在校准结束且将校准值存储在Eprom中后清零
            buffer = ucReceiveData[4] + ucReceiveData[5]*256;
            if(buffer>2500)    buffer = 1000;
            ImpactPara.CaliShockAcce = buffer;
            ImpactPara.ShakerNum=ucReceiveData[6];
            SlectShaker(ImpactPara.ShakerNum);    // 选择相应的振动台
            ACCEDISP=ReceiveCalCoeff[2*(ImpactPara.ShakerNum-1)];     // 冲击加速度值与电压值之间的转换系数
            Usart_ShockParaSet();
        break;
        case UARTSHOCK:
             bComputerRunFlag=1;            // 上位机正在控制振动台动作,禁止下位机工作
            buffer = ucReceiveData[4] + ucReceiveData[5]*256;
            if (ucReceiveData[7])             // 开闭环数据,余加
            {
                if (buffer>70) buffer=70;
                bLoopFlag = OPENLOOP;
                ImpactPara.Volt = buffer;
            }
            else
            {
                if(buffer>2500)    buffer = 1000;
                bLoopFlag = CLOSELOOP;
                ImpactPara.CaliShockAcce = buffer;
            }
            ImpactPara.CaliShockAcce = buffer;
            ImpactPara.ShakerNum=ucReceiveData[6];
            SlectShaker(ImpactPara.ShakerNum);    // 选择相应的振动台
            ACCEDISP=ReceiveCalCoeff[2*(ImpactPara.ShakerNum-1)];     // 冲击加速度值与电压值之间的转换系数
            Usart_ShockParaSet();                    
        break;
        case MANSHOCK:                        // 产生一次冲击信号,模拟在手动冲击界面下按下确定键
            SelectAcce = 1;                    // 默认选择冲击加速度
            SinglePulse();                    // 产生一次冲击
//            ET0 = 0;
            SampleShockAcce();                // 计算冲击加速度值   
            SendUARTSHOCKACCE(); //向上位机发送冲击校准加速度
        break;
        case SHOCKSTOP:                        // 停止冲击方式,在手动冲击方式下停止         
             Usart_ShockParaSet();
             bComputerRunFlag=0;            // 上位机控制振动台动作结束,下位机可以操作按键控制振动台工作
        break;
        case CHANGESHAKER:
             if(ucReceiveData[4]>=1&&ucReceiveData[4]<=3)                     // 振动台号1-3
            {
                VibraPara.ShakerNum = ucReceiveData[4];         
            }
             SlectShaker(VibraPara.ShakerNum);    // 选择相应的振动台
        break;
        case UARTVIBRA:                        // 连续振动方式,模拟在菜单2的情况下按下确定键
            if(ucReceiveData[4]>=13&&ucReceiveData[4]<=250)                        // 找出振动频率
            {
                VibraPara.Frequency = ucReceiveData[4];
            }            
            if(ucReceiveData[5]>=10&&ucReceiveData[5]<=250)                     // 振动加速度
            {
                VibraPara.Volt = ucReceiveData[5];         
            }
            if(ucReceiveData[6]>=1&&ucReceiveData[6]<=3)                     // 振动台号1-3
            {
                VibraPara.ShakerNum = ucReceiveData[6];         
            }
            bComputerRunFlag=1;            // 上位机正在控制振动台动作,禁止下位机工作
//            CommandType=0x20;         // 振动台正在做连续振动
            SlectShaker(VibraPara.ShakerNum);    // 选择相应的振动台
            VIBRAVOLT=ReceiveCalCoeff[2*ImpactPara.ShakerNum-1];     // 振动加速度值与电压值之间的转换系数
            
            if(ucReceiveData[7]==0)          bLoopFlag = CLOSELOOP;            // 开闭环数据,余加
            else     bLoopFlag = OPENLOOP;
            

            EA = 0;                    
            Usart_VibraParaSet();                    
            EA = 1;
        break;
        case VIBRASTOP:            //连续振动停止
             Usart_VibraParaSetStop();
             bComputerRunFlag=0;            // 上位机控制振动台动作结束,下位机可以操作按键控制振动台工作
//             CommandType=0;
        break;
        case UARTSCAN:
//            TR0 = 0;
            if(ucReceiveData[4]>=0&&ucReceiveData[4]<=250)                         // 扫频振动起始频率
            {
                ScanPara.StartFre = ucReceiveData[4];
            }
            if(ucReceiveData[5]>=0&&ucReceiveData[5]<=250)                        // 扫频振动截止频率
            {
                ScanPara.EndFre = ucReceiveData[5];
            }
            if(ucReceiveData[6]>=1&&ucReceiveData[6]<=10)                          // 扫频振动步进时间
            {
                ScanPara.StepTime = ucReceiveData[6];
            }
            if(ucReceiveData[7]>=10&&ucReceiveData[7]<=220)                       // 扫频振动振动加速度
            {
                ScanPara.Volt = ucReceiveData[7];                    
            }
            if(ucReceiveData[8]>=1&&ucReceiveData[8]<=3)                       // 振动台号1-3
            {
                ScanPara.ShakerNum = ucReceiveData[8];                    
            }
            bComputerRunFlag=1;            // 上位机正在控制振动台动作,禁止下位机工作
            SlectShaker(ScanPara.ShakerNum);    // 选择相应的振动台
            VIBRAVOLT=ReceiveCalCoeff[2*ImpactPara.ShakerNum-1];     // 振动加速度值与电压值之间的转换系数        
            bLoopFlag = CLOSELOOP;
            EA = 0;
            Usart_ScanParaSet();                                      
            EA = 1;   
        break;
        case SCANSTOP:   
             Usart_ScanParaStop();
             bComputerRunFlag=0;            // 上位机控制振动台动作结束,下位机可以操作按键控制振动台工作
        break;
        case RUNPROGRAM:            
        break;
        case RUNDEFAULTPROGRAM:
             RunShakerNumFlag=0;
             RunShakerNumToll=DefaultShaker[0]+DefaultShaker[1]+DefaultShaker[2];  // 记录默认工作振动台数目
             ShakerRunProgFlag=1;            // 启动运行方案
             bComputerRunFlag=1;            // 上位机控制振动台动作结束,下位机可以操作按键控制振动台工作
             CommandType=0x01;                // 振动台正在执行方案
             DISABLEFAILLEDAll;                  // 失效指示灯熄灭
             longDELAY(100);
        break;
        case RUNPROGRAMSTOP:                // 全速运行方式停
             TimeBetwProgCount=0;    // 两个连续运行的方案之间的时间间隔,对timer1计数
             ShakerRunProgFlag=0;    // 振动台正在运行方案标志位
             RunShakerNumToll=0;      // 默认工作振动台总数
             RunShakerNumFlag=0;    // 选择当前工作振动台
             Usart_RunProgramStop();
             bComputerRunFlag=0;            // 上位机控制振动台动作结束,下位机可以操作按键控制振动台工作上位机强制停止时,标志位清零方案运行结束时,标志位清零
             CommandType=0x00;                //
        break;                             
        case STOPCURSHAKER:                // 上位机中途停止运行方案
             if((TR1 == 0)&&(1==CommandType))
             {            
                 Usart_RunProgramStop();//
                 longDELAY(100);
                 bExecuteFlag=1;        // 方案运行结束标志位
             }   
        break;
        case ANALYSERESULT:
             for(i=0;i<3;i++)
             {
                 if(ucReceiveData[4])
                {
                EnableFailLed(1);
                }
                else
                {
                  DisableFailLed(1);
                }
             }         
            ucParticleNum = 0;            
        break;
        case SENDCALCOEFF:
            fAcceleration.uchar_kind[3]=ucReceiveData[5];    // 上位机与下位机数据存储格式相反
            fAcceleration.uchar_kind[2]=ucReceiveData[6];
            fAcceleration.uchar_kind[1]=ucReceiveData[7];
            fAcceleration.uchar_kind[0]=ucReceiveData[8];

//            bufferCoeff=fAcceleration.float_kind;
            buffer=CalCoeffADD+ucReceiveData[4]*4;
        
//            SM_Receive (AT24C256N1,buffer,CalCoeff4,4);      //  读入校准系数
//            for(i=0;i<4;i++)      fAcceleration.uchar_kind=CalCoeff4;
   
            ReceiveCalCoeff[ucReceiveData[4]] = fAcceleration.float_kind ;

            for(i=0;i<4;i++)      CalCoeff4=fAcceleration.uchar_kind;
            SM_Send (AT24C256N1,buffer,CalCoeff4,4);      //  存储新的校准系数


        break;
        case READCALCOEFF:                    
            buffer=CalCoeffADD+ucReceiveData[4]*4;                        
            SM_Receive (AT24C256N1,buffer,CalCoeff4,4);      //  读入校准系数
            SendReadCoeff()    ;  // 发送校准系数
        break;
        case SETPARAMETER:
             for(i=0;i<3;i++)
             {
                DefaultProgrNum=ucReceiveData[4+i];
                DefaultShaker=ucReceiveData[7+i];
                if(0==DefaultProgrNum)
                    DefaultShaker=0;
                                 
             }
             TimeBetweenProg[0]=ucReceiveData[10];
             TimeBetweenProg[1]=ucReceiveData[11];
             SM_Send (AT24C256N1,DefaultProgrNumADD,DefaultProgrNum,3);      //  存储振动台的默认方案
             SM_Send (AT24C256N1,DefaultShakerADD,DefaultShaker,3);          //  存储默认工作的振动台
             SM_Send (AT24C256N1,TimeBetweenProgADD,TimeBetweenProg,2);      //  存储默认工作的振动台
        break;
        case READPARAMETER:
             SendReadParameter();
        break;
          case SENDPROGRAM:                                                        // 接收上位机发送的方案
            if(ucReceiveData[4]>0&&ucReceiveData[4]<=TotalProgram)
            {
                ucProgramNum = ucReceiveData[4];
                ucTotalInst[ucProgramNum-1] = 0;                                // 将该方案中的指令数清0,表示没有指令
            }
            ReceiveCommand();             // 读取接收的方案指令
        break;
        case READPROGRAM:
            if(ucReceiveData[4]>0&&ucReceiveData[4]<=TotalProgram)                   // 接收方案有问题,由8改为TotalProgram,余改

            {
                ucProgramNum = ucReceiveData[4];                                // 需要读入的方案数        
            }
             SendCommand();
        break;
        case REQUESTVIBRAACCE:                                           // 发送方案运行过程中的振动加速度,余加
            fAcceleration.float_kind=PeakAverage()*VIBRAVOLT;
            UsartSampleAcce();
        break;
        break;
        default:
        break;
    }
    for(i=0;i<12;i++)
    {
        ucReceiveData = NOTHING;            // 清空接收缓冲区,为下一次接收数据做准备
        ucReceState = 0;                     // 将接受状态清0,为下一次通讯准备
    }
}

//---------------------------------------------------------------------------------------
// 此程序用于向上位机发送数据,或为应答数据,或为询问数据,应答数据为从方式,询问数据为主
// 方式,通知上位机本次通讯的状态
//---------------------------------------------------------------------------------------
void SendReadCoeff()
{
    uchar i;

    ucSendData[0] = UARTDLE;
    ucSendData[1] = UARTSTX;
    ucSendData[2] = ACK;
    ucSendData[3] = ucReceState;            // 发送接收成功或失败的代码
    ucSendData[4] = ucReceiveData[3];
    ucSendData[5] =CalCoeff4[3];
    ucSendData[6] =CalCoeff4[2];
    ucSendData[7] =CalCoeff4[1];
    ucSendData[8] =CalCoeff4[0];
    ucSendData[9] = UARTDLE;
    ucSendData[10] = UARTETX;
   
    for(i=0;i<11;i++)                        // 向上位机发送数据
    {
        SBUF0 = ucSendData;
        while(TI0==0);
        TI0=0;
    }
}

//---------------------------------------------------------------------------------------
// 此程序用于向上位机发送数据,或为应答数据,或为询问数据,应答数据为从方式,询问数据为主
// 方式,通知上位机本次通讯的状态
//---------------------------------------------------------------------------------------
void SendUartData()
{
    uchar i;

    ucSendData[0] = UARTDLE;
    ucSendData[1] = UARTSTX;
    ucSendData[2] = ACK;
    ucSendData[3] = ucReceState;            // 发送接收成功或失败的代码
    ucSendData[4] = ucReceiveData[3];
    if (ucReceiveData[3]==SELFCHECK)
    {
        ucSendData[5] = CommandType;
    }
    else
    {
        ucSendData[5] = 0x00;
    }
    ucSendData[6] = UARTDLE;
    ucSendData[7] = UARTETX;
   
    for(i=0;i<8;i++)                        // 向上位机发送数据
    {
        SBUF0 = ucSendData;
        while(TI0==0);
        TI0=0;
    }
}
//---------------------------------------------------------------------------------------
// 此程序用于处理上位机已经编辑好的方案数据,将方案中的数据以指令的形式提取出来,并保存在
// 外部存储器中。
//---------------------------------------------------------------------------------------
void ReceiveCommand()
{
    uchar i;
    uchar pos;
    uint  Address;
    for(i=0;i<ucReceiveData[5];i++)
    {
        pos = 6+i*4;
        if(i==0)    ucSendInstruction[0+i*5] = STX;
        else        ucSendInstruction[0+i*5] = 0x00;
        if(ucReceiveData[pos]==UARTVIBRA)    ucSendInstruction[1+i*5] = VIBRA;
        if(ucReceiveData[pos]==UARTSHOCK)    ucSendInstruction[1+i*5] = SHOCK;
        ucSendInstruction[2+i*5] = ucReceiveData[pos+1];                             // 振动频率/冲击脉宽
        ucSendInstruction[3+i*5] = ucReceiveData[pos+2];                            // 振动幅值/冲击幅值
        ucSendInstruction[4+i*5] = ucReceiveData[pos+3];                               // 振动时间/冲击次数        
        ucTotalInst[ucProgramNum-1] = ucTotalInst[ucProgramNum-1]+1;
    }
    Address=(0X0000+(ucProgramNum-1)<<6);
    SM_Send(AT24C256N1,Address,ucSendInstruction,5*ucTotalInst[ucProgramNum-1]);     // 将每个方案的指令一次存入e2prom中
    ucSendInstruction[0] = ucTotalInst[ucProgramNum-1];                       
    Address=TotleInstrucADD+(ucProgramNum-1);  
    SM_Send(AT24C256N1,Address,ucSendInstruction,1);                    // 将该方案包含的指令数写入存储器中
//    SM_Receive(AT24C256N1,TotleInstrucADD,ucSendInstruction,8);                    // 将该方案包含的指令数写入存储器中
}
//-------------------------------------------------------------------------------------------
// 从EPROM中读入方案的指令,并提取有效的指令
//-------------------------------------------------------------------------------------------
void ReadCommand(void)
{
    uchar pos;
    uchar pos2;
    uchar i;
    uint Address;
    Address=(0X0000+(ucProgramNum-1)<<6);
    ET0=0;
    SM_Receive(AT24C256N1,Address,ucSendInstruction,5*ucTotalInst[ucProgramNum-1]);     // 将每个方案的指令一次存入e2prom中
    for(i=0;i<ucTotalInst[ucProgramNum-1];i++)
    {
        pos = i*4;
        pos2 = i*5;   
        ucReadCommand[pos]   = ucSendInstruction[pos2+1];                    // 将读取的缓冲区中的指令存储到指定位置
        ucReadCommand[pos+1] = ucSendInstruction[pos2+2];              
        ucReadCommand[pos+2] = ucSendInstruction[pos2+3];
        ucReadCommand[pos+3] = ucSendInstruction[pos2+4];
    }
    ET0=1;   
}
//---------------------------------------------------------------------------------------
// 此程序用于向上位机发送其指定的方案。现将方案的指令从外部存储器中读取出来,再以数据包的
// 形式发给上位机
//---------------------------------------------------------------------------------------
void SendCommand()
{
    uchar i,j,pos=0,pos2;
    uchar length;
    uchar count_ten = 0;
    uint Address;
   
    ucSendData[0] = UARTDLE;
    ucSendData[1] = UARTSTX;
    ucSendData[2] = ACK;
    ucSendData[3] = ucReceState;
    ucSendData[4] = ucReceiveData[3];
    ucReceState = 0;                                                            // 清零,准备接收下一桢数据
    Address=(0X0000+(ucProgramNum-1)<<6);
    ET0=0;
    SM_Receive(AT24C256N1,Address,ucSendInstruction,5*ucTotalInst[ucProgramNum-1]);     // 将每个方案的指令一次存入e2prom中
    for(i=0;i<ucTotalInst[ucProgramNum-1];i++)                               // 将读取的缓冲区中的指令存储到指定位置
    {
        pos =5+i*4;
        pos2 = i*5;   
        if(ucSendInstruction[pos2+1]==VIBRA)        ucSendData[pos] = UARTVIBRA;
        else if(ucSendInstruction[pos2+1]==SHOCK)    ucSendData[pos] = UARTSHOCK;                        
        ucSendData[pos+1] = ucSendInstruction[pos2+2];              
        ucSendData[pos+2] = ucSendInstruction[pos2+3];
        ucSendData[pos+3] = ucSendInstruction[pos2+4];
    }
    ET0=1;   
    ucSendData[pos+4] = UARTDLE;
    ucSendData[pos+5] = UARTETX;

    length = pos+6;
    for(i=length-3;i>=2;i--)                // 判断发送的有效收据是否含有0x10,如果有,再添加一个0x10
    {
        if(ucSendData==0x10)
        {            
            count_ten++;
            for(j=length-1+count_ten;j>i;j--)
            {        
                 ucSendData[j]=ucSendData[j-1];
            }
        }   
    }
    length = length+count_ten;
    for(i=0;i<length;i++)                    // 发送指令
    {
        SBUF0 = ucSendData;
        while(TI0==0);
        TI0=0;   
    }
}
//---------------------------------------------------------------------------------------
// Usart_VibraDetectorCal,实现振动加速度前向检测通道校准,包括零位校准
// 和增益校准
//---------------------------------------------------------------------------------------
void Usart_VibraDetectorCal(void)
{  
    if(bZeroCalFlag==TRUE)      // 开始零位校准
    {  
        VIBDETSETZERO;            // 使能零位校准,也是系统的初始状态                                 
    }
    if(bGainCalFlag==TRUE)      // 开始增益校准
    {         
        VIBDETSETGAIN;            // 使能增益校准
    }
   
    VIBRACALVOLT =     ReceiveCalCoeff[7];
    ucSampleNumber = 200;       // 计算200个点的平均值
    //fCoefficient = 853.3;       // 2048/2.4                     
    fVirtualValue = 0;        // 赋初值
    AD0EN = 1;                  // 使能AD,开始采集

   
}
void Usart_VibraDetectorCalStop(void)
{
    if(bZeroCalFlag==TRUE||bGainCalFlag==TRUE)
    {
        AD0EN = 0;
        ucPeakCount = 0;
        nWaveCount = 0;
        bZeroCalFlag = FALSE;
        bGainCalFlag = FALSE;
        INISTATE;                   // 系统的初始状态
    }
}
void Usart_ShockDetectorCal(void)
{  
    if(bZeroCalFlag==TRUE)      // 开始零位校准
    {  
        SHOCKDETSETZERO;            // 使能零位校准                                    
    }
    if(bGainCalFlag==TRUE)      // 开始增益校准
    {         
        SHOCKDETSETGAIN;            // 使能增益校准
    }
    SHOCKCALVOLT =     ReceiveCalCoeff[6];   
    ucSampleNumber = 200;       // 计算200个点的平均值
    fCoefficient = 106.67;       // 2048/2.4                  
    fVirtualValue = 0;        // 赋初值
    EAABLEADC1C;                  // 使能AD,开始采集
}
void Usart_ShockDetectorCalStop(void)
{  
    if(bZeroCalFlag==TRUE||bGainCalFlag==TRUE)
    {     
        DISABLEADC1;
        ucPeakCount = 0;
        nWaveCount = 0;  
        bZeroCalFlag = FALSE;
        bGainCalFlag = FALSE;
        INISTATE;               // 系统的初始状态
    }
}
void Usart_VibraParaSet(void)    //    启动振动台开始振动
{
//    ucScaleValue = 1;             //设置振动台参数时,该变量表征增减的步进值
    VIBRAPARASET;                   // 选择振动加速度
    ucSampleNumber = 10000/VibraPara.Frequency;                 // 根据振动频率计算加速度一个周期的采样点数   
    AD0EN = 0;
    //fCoefficient = 853.3*sqrt(ucSampleNumber);             // 2048/2.4=853.3
    fInput = (float)VibraPara.Volt/10;                           // 为了存储方便,加速度的值为其存储值的十分之一
    //  fInput = fInput/15.38/1.499;
    fInput = AcceToVolt(fInput);
    Vibration(VibraPara.Frequency,VibraPara.Volt);                          // 输出正弦波,使振动台开始振动   
    AD0EN = 1;                 // 开AD中断,开始对振动加速度进行采集
}
void Usart_VibraParaSetStop(void)    //    停止振动台振动
{
    AD0EN = 0;
    ucPeakCount = 0;
    nWaveCount = 0;
    Stop();
    INISTATE;                   // 系统的初始状态
}

//---------------------------------------------------------------------------------------
// 此程序用于显示连续振动、扫频振动、方案运行及振动冲击校准方式下的振动加速度和冲击加速度
// 并在显示之前对AD采集的数据进行了处理。该程序通过结构体DISPACCE的type变量判断振动台的工
// 作方式,并执行与之对应的加速度处理及显示程序。
//---------------------------------------------------------------------------------------
void UsartSampleAcce()
{     

   //   ucPeakCount = 0;                        //
    switch(ucUsartSampleAcce)                // 通过判断接收的第三个数据判断指令类型
    {
        case UARTVIBRAZERO:                 // 振动通道零位校准
        case UARTVIBRAGAIN:                      // 振动通道增益校准
        //     fAcceleration.float_kind=PeakAverage()*VIBRACALVOLT;
             SendUartAcce(ucUsartSampleAcce);
        break;
        case UARTSHOCKZERO:                      // 冲击通道零位校准
        case UARTSHOCKGAIN:                      // 振动通道增益校准
            // fAcceleration.float_kind=PeakAverage()*SHOCKCALVOLT;
             SendUartAcce(ucUsartSampleAcce);
        break;
        case UARTVIBRA:                          // 连续振动
        //     fAcceleration.float_kind=PeakAverage()*VIBRAVOLT;
             SendUartAcceShaker();
        break;
        case UARTSCAN:
        //     fAcceleration.float_kind=PeakAverage()*VIBRAVOLT;
             SendFrequency(ScanPara.Frequency);
             SendUARTSCAN();              
        break;
        case REQUESTVIBRAACCE:
             SendUartAcce(ucUsartSampleAcce);
        break;
        default:
        break;
   
    }

}
//--------------------------------------------------------------------------
void CalculSampleAcce()
{     
      ucPeakCount = 0;                        //
    switch(ucUsartSampleAcce)                // 通过判断接收的第三个数据判断指令类型
    {
        case UARTVIBRAZERO:                 // 振动通道零位校准
        case UARTVIBRAGAIN:                      // 振动通道增益校准
             fAcceleration.float_kind=PeakAverage()*VIBRACALVOLT;
            
        break;
        case UARTSHOCKZERO:                      // 冲击通道零位校准
        case UARTSHOCKGAIN:                      // 振动通道增益校准
             fAcceleration.float_kind=PeakAverage()*SHOCKCALVOLT;
            
        break;
        case UARTVIBRA:                          // 连续振动
             fAcceleration.float_kind=PeakAverage()*VIBRAVOLT;
        
        break;
        case UARTSCAN:
             fAcceleration.float_kind=PeakAverage()*VIBRAVOLT;
             SendFrequency(ScanPara.Frequency);                  
        break;     
        default:
        break;
   
    }

}      
                    
      
//---------------------------------------------------------------------------------------
// 此函数用于计算采集的加速度的平均值,基本算法是去掉一个最大值和最小值,再求取剩下23个数
// 据的平均值。返回值即为计算求得的平均值。
//---------------------------------------------------------------------------------------
float PeakAverage()
{
       float MaxPeak = 0;
    float MinPeak = 100;
    float PeakAverage = 0;
    uchar i;

    PeakAverage = 0;      
    MaxPeak=MinPeak=fVirtualBuffer[0];                           
    for(i=1;i&lteakCountNUM;i++)                         // 求取最大值和最小值
    {
        if(fVirtualBuffer>MaxPeak)
        {
            MaxPeak = fVirtualBuffer;
        }
        if(fVirtualBuffer<MinPeak)
        {
            MinPeak = fVirtualBuffer;
        }                    
        PeakAverage = fVirtualBuffer+PeakAverage;
    }                     
    PeakAverage = PeakAverage - MaxPeak;       // 剔除最大值和最小值,计算剩余值的平均值做为最终值
    PeakAverage = PeakAverage - MinPeak;
    PeakAverage = PeakAverage/(PeakCountNUM-2);
    if(UARTVIBRAZERO==ucUsartSampleAcce)  PeakAverage -= 0.023;
    //if(UARTSHOCKZERO==ucUsartSampleAcce)  PeakAverage -= 0.0035;
    return PeakAverage;
}

//---------------------------------------------------------------------------------------
// 此程序用于向上位机主动发送命令,主要用于在振动台执行全速运行方案的时候,通知上位机冲击
// 已经结束,可以进行噪声采集,同时,方案运行完毕时也发送一个命令,入口参数表示是否是允许
// 采集或者运行结束
//---------------------------------------------------------------------------------------
void SendSampleVibra(uchar type)
{
    uchar i;
    uchar SendNum;

    ucSendData[0] = UARTDLE;
    ucSendData[1] = UARTSTX;
    ucSendData[2] = REQUEST;
    ucSendData[3] = type;                    // 发送接收成功或失败的代码
    ucSendData[4] = UARTDLE;
    ucSendData[5] = UARTETX;
    SendNum=6;
    if(type==STARTRUN)
    {
        ucSendData[2] =ucProgramNum;
        SendNum=6;   
    }
    if(type==SELFCHECK)
    {
        ucSendData[4] = 1;
        ucSendData[5] = UARTDLE;
        ucSendData[6] = UARTETX;
        SendNum=7;
    }
    if(type==ENABLESAMPLE)                    // 通知上位机开始采集振动波形
    {
        ucSendData[2] = ucReadCommand[ucRunCommandPos+3];
        if (bShockCommand)
        {
            ucSendData[2] = ucSendData[2] | 0x80;             // 发送振动时间,将冲击标志位和震动时间合并在一个字节里
        }

        ucSendData[4] = ImpactPara.ShakerNum;
        ucSendData[5] = ucReadCommand[ucRunCommandPos+1];    //振动频率
        ucSendData[6] = 0;
        ucSendData[7] = 0;
        ucSendData[8] = 0;
        //ucSendData[4] = ucReadCommand[ucRunCommandPos+1];    //这个字节改为传输当前振动频率
        //fAcceleration.float_kind =shockacceprog;        
        //    for(i=0;i<4;i++)      ucSendData[i+5]=fAcceleration.uchar_kind[3-i];

        //ucSendData[2] = ucReadCommand[ucRunCommandPos+3];             // 发送振动时间
        //ucSendData[4] =    ImpactPara.ShakerNum;
        ucSendData[9] = UARTDLE;
        ucSendData[10] = UARTETX;
        SendNum=11;
    }
    for(i=0;i<SendNum;i++)                        // 向上位机发送数据
    {
        SBUF0 = ucSendData;
        while(TI0==0);
        TI0=0;
    }
}
//---------------------------------------------------------------------------------------
// 此程序用于向上位机校准的加速度
// 括振动和冲击的零位及增益校准
//---------------------------------------------------------------------------------------
void SendUartAcce(uchar type)                 // 函数入口参数进行了修改,余加
{
    uchar i;

    ucSendData[0] = UARTDLE;
    ucSendData[1] = UARTSTX;
    ucSendData[2] = REQUEST;                          // 发送数据
    ucSendData[3] = type;            // 指令类型
    ucSendData[4] = fAcceleration.uchar_kind[3];
    ucSendData[5] = fAcceleration.uchar_kind[2];
    ucSendData[6] = fAcceleration.uchar_kind[1];
    ucSendData[7] = fAcceleration.uchar_kind[0];
    ucSendData[8] = UARTDLE;
    ucSendData[9] = UARTETX;
    for(i=0;i<10;i++)                        // 向上位机发送数据
    {
        SBUF0 = ucSendData;
        while(TI0==0);
        TI0=0;
    }
}
//---------------------------------------------------------------------------------------
// 此程序用于向上位机发送连续振动的加速度
//
//---------------------------------------------------------------------------------------
void SendUartAcceShaker(){
    uchar i;

    ucSendData[0] = UARTDLE;
    ucSendData[1] = UARTSTX;
    ucSendData[2] = REQUEST;                          // 发送数据
    ucSendData[3] = ucUsartSampleAcce;            // 指令类型
    ucSendData[4] = fAcceleration.uchar_kind[3];
    ucSendData[5] = fAcceleration.uchar_kind[2];
    ucSendData[6] = fAcceleration.uchar_kind[1];
    ucSendData[7] = fAcceleration.uchar_kind[0];
    ucSendData[8] = VibraPara.ShakerNum;
    ucSendData[9] = UARTDLE;
    ucSendData[10] = UARTETX;
    for(i=0;i<11;i++)                        // 向上位机发送数据
    {
        SBUF0 = ucSendData;
        while(TI0==0);
        TI0=0;
    }
}
//---------------------------------------------------------------------------------------
// 此程序用于向上位机发送扫频振动的加速度
//
//---------------------------------------------------------------------------------------
void SendUARTSCAN(void)
{
    uchar i;

    ucSendData[0] = UARTDLE;
    ucSendData[1] = UARTSTX;
    ucSendData[2] = REQUEST;                          // 发送数据
    ucSendData[3] = ucUsartSampleAcce;            // 指令类型
    ucSendData[4] = fAcceleration.uchar_kind[3];
    ucSendData[5] = fAcceleration.uchar_kind[2];
    ucSendData[6] = fAcceleration.uchar_kind[1];
    ucSendData[7] = fAcceleration.uchar_kind[0];
    ucSendData[8] = ScanPara.Frequency;
    ucSendData[9] = ScanPara.ShakerNum;
    if(bScanEndFlag)
        ucSendData[10] = TRUE;
    else
        ucSendData[10] = FALSE;
    ucSendData[11] = UARTDLE;
    ucSendData[12] = UARTETX;
    for(i=0;i<13;i++)                        // 向上位机发送数据
    {
        SBUF0 = ucSendData;
        while(TI0==0);
        TI0=0;
    }
}
void SendUARTSHOCKACCE(void)
{
    uchar i;

    ucSendData[0] = UARTDLE;
    ucSendData[1] = UARTSTX;
    ucSendData[2] = REQUEST;                          // 发送数据
    ucSendData[3] = ucUsartSampleAcce;            // 指令类型
    ucSendData[4] = fAcceleration.uchar_kind[3];
    ucSendData[5] = fAcceleration.uchar_kind[2];
    ucSendData[6] = fAcceleration.uchar_kind[1];
    ucSendData[7] = fAcceleration.uchar_kind[0];
    ucSendData[8] = ImpactPara.ShakerNum;
    ucSendData[9] = UARTDLE;
    ucSendData[10] = UARTETX;
    for(i=0;i<11;i++)                        // 向上位机发送数据
    {
        SBUF0 = ucSendData;
        while(TI0==0);
        TI0=0;
    }
}
//---------------------------------------------------------------------------------------
// 此程序用于向上位机发送默认工作的振动台号及默认的方案号
//---------------------------------------------------------------------------------------
void SendReadParameter()
{
    uchar i;

    ucSendData[0] = UARTDLE;
    ucSendData[1] = UARTSTX;
    ucSendData[2] = ACK;
    ucSendData[3] = ucReceState;
    ucSendData[4] = ucUsartSampleAcce;     
    for(i=0;i<3;i++)
    {
        ucSendData[5+i]=DefaultProgrNum;    //默认的方案号
        ucSendData[8+i]=DefaultShaker;   // 默认的振动台号               
    }
    ucSendData[11] = TimeBetweenProg[0];    // 运行方案的时间间隔
    ucSendData[12] = TimeBetweenProg[1];    // 运行方案的时间间隔
       ucSendData[13] = UARTDLE;
    ucSendData[14] = UARTETX;
    for(i=0;i<15;i++)                        // 向上位机发送数据
    {
        SBUF0 = ucSendData;
        while(TI0==0);
        TI0=0;
    }
}
//--------------------------------------------------------------------------------------------
// 延时程序,用于较短的延时
//--------------------------------------------------------------------------------------------
void DELAY(uchar a)                              
{
    uchar i,j;

    for(i=0;i<a;i++)
        for(j=0;j<70;j++);
}
//--------------------------------------------------------------------------------------------
// 延时程序,用于较长时间的延时
//--------------------------------------------------------------------------------------------
void longDELAY (uint a)                        
{
    int i,j;

    for(i=1;i<=a;i++)
      for(j=1;j<=11776;j++);
}

void SampleShockAcceProg(void)
{
    uchar     i;
    long     count = 0;

    ucSampleShockCount = 0;   
    while(Impacted==1)
    {
        count++;   
        if(count>25000)        break;          // 防止振动台没撞击上底座,导致Particle没有变化造成死循环
    }   

    //DELAY(11);        
    ENABLEADC1;            
    while(ucSampleShockCount<40);               // 等待采样20次
    DISABLEADC1;                             // 禁止ADC1
      
    shockacceprog = 0;      
    for(i=10;i<30;i++)                      // 求取最后20个值的平均值作为最终值,因为最后20个值峰值保持电路已经将冲击加速度保持住
    {
        shockacceprog = shockacceprog + ucShockVolt;
    }
    shockacceprog = shockacceprog*ACCEDISP/20;
    ucSampleShockCount=0;
}

uint SampleShockAcce(void)
{
    uint pdata     accebuffer;
    long     count = 0;
    uchar     i;
    float     shockacce = 0;
//    float    fcoff;
    float   resetvalue = 0;

    ucSampleShockCount = 0;   
    while(Impacted==1)
    {
        count++;   
        if(count>25000)        break;          // 防止振动台没撞击上底座,导致Particle没有变化造成死循环
    }
    //ResetRelay = 1;
    DELAY(11);
    //ResetRelay = 0;            
    ENABLEADC1;            
    while(ucSampleShockCount<40);               // 等待采样20次
    DISABLEADC1;                             // 禁止ADC1
    //ResetAcce = 0;                            // 保持电路放电,为下次冲击准备
    P6 &= 0xfd;
    longDELAY(70);                                   
    //ResetAcce = 1;                            // 保持电路继续有效
    P6 |= 0x02;
    longDELAY(7);           
    for(i=10;i<40;i++)                      // 求取最后20个值的平均值作为最终值,因为最后20个值峰值保持电路已经将冲击加速度保持住
    {
        shockacce = shockacce + ucShockVolt;
    }
    shockacce = shockacce/30;
    ucSampleShockCount=0;
/* ENABLEADC1
    while(ucSampleShockCount<20);           // 求取复位时的电平值
    DISABLEADC1
    for(i=0;i<ucSampleShockCount;i++)      
    {
        resetvalue = resetvalue + ucShockVolt;              
    }
    resetvalue =  resetvalue/ucSampleShockCount;
    max = max -  resetvalue;               // 最大值减去复位状态下的电平值即为实际值
    secondmax = secondmax - resetvalue;   */
    //shockacce = shockacce/106.67;
    //shockacce = shockacce/1.05;                // 折算成传感器输出的最大冲击电压
/*    if(shockacce<=0.2)                        // 如果电压小于200mv,转换系数都为800
    {
        accebuffer = (uint)(shockacce*800);
    }
    else if(shockacce>=1.0)
    {
        accebuffer = (uint)(shockacce*1000);
    }
    else
    {
        fcoff = 250*shockacce+750;
        accebuffer = (uint)(shockacce*fcoff);
    }*/
         
    accebuffer = (uint)(shockacce*ACCEDISP);
    fAcceleration.float_kind=accebuffer;         
    return accebuffer;
}

// 测量方案运行过程中冲击加速度大小,和上个函数的区别是延时时间变短,留有足够的计算时间,余加
uint SampleRunShockAcce(void)
{
    uint pdata     accebuffer;
    long     count = 0;
    uchar     i;
    float     shockacce = 0;
//    float    fcoff;
    float   resetvalue = 0;

    ucSampleShockCount = 0;   
    while(Impacted==1)
    {
        count++;   
        if(count>25000)        break;          // 防止振动台没撞击上底座,导致Particle没有变化造成死循环
    }
    //ResetRelay = 1;
    DELAY(11);
    //ResetRelay = 0;            
    ENABLEADC1;            
    while(ucSampleShockCount<40);               // 等待采样20次
    DISABLEADC1;                             // 禁止ADC1
    //ResetAcce = 0;                            // 保持电路放电,为下次冲击准备
    P6 &= 0xfd;
    longDELAY(20);                                   // 70变为40,为计算方案运行过程中冲击加速度留有足够的计算时间,余加
    //ResetAcce = 1;                            // 保持电路继续有效
    P6 |= 0x02;
    longDELAY(7);           
    for(i=10;i<40;i++)                      // 求取最后20个值的平均值作为最终值,因为最后20个值峰值保持电路已经将冲击加速度保持住
    {
        shockacce = shockacce + ucShockVolt;
    }
    shockacce = shockacce/30;
    ucSampleShockCount=0;
/* ENABLEADC1
    while(ucSampleShockCount<20);           // 求取复位时的电平值
    DISABLEADC1
    for(i=0;i<ucSampleShockCount;i++)      
    {
        resetvalue = resetvalue + ucShockVolt;              
    }
    resetvalue =  resetvalue/ucSampleShockCount;
    max = max -  resetvalue;               // 最大值减去复位状态下的电平值即为实际值
    secondmax = secondmax - resetvalue;   */
    //shockacce = shockacce/106.67;
    //shockacce = shockacce/1.05;                // 折算成传感器输出的最大冲击电压
/*    if(shockacce<=0.2)                        // 如果电压小于200mv,转换系数都为800
    {
        accebuffer = (uint)(shockacce*800);
    }
    else if(shockacce>=1.0)
    {
        accebuffer = (uint)(shockacce*1000);
    }
    else
    {
        fcoff = 250*shockacce+750;
        accebuffer = (uint)(shockacce*fcoff);
    }*/
         
    accebuffer = (uint)(shockacce*ACCEDISP);
    return      accebuffer;
}
//-----------------------------------------------------------------------------------------------
//  此程序用于振动闭环控制时将给定加速度转换成AD620电压值,入口参数为给定加速度值,返回值为加速度
//------------------------------------------------------------------------------------------------
float AcceToVolt(float acce)
{
    float volt;

    volt = acce/VIBRAVOLT;                    // 将输入加速度值转换为AD620输出的电压
    /*if(volt<0.6)                            // AD620输出电压和单片机采集的电压之间存在一个非线性关系,由此二次多项式求出
        volt = volt/1.06;
    else
        volt = -0.1429*volt*volt+0.9317*volt+0.063;*/   
    return volt;
}
//---------------------------------------------------------------------------------
// 此程序输出正弦波,使振动台工作在振动状态,入口参数为振动频率及其振动幅值
//---------------------------------------------------------------------------------
void Vibration(uchar frequency,uchar volt)
{
    SelectAcce = 0;                                    // 选择振动加速度
//    ResetRelay = 1;                                    // 峰值保持有效
//    CalibrateAcce = 0;                                // 校准振动加速度
    SendFrequency(frequency);                        // 发送振动频率值
    SetVibraInput(frequency,volt);         // 为了缩短闭环调节时间,快使地给定一个DA输出值,使振动台快速地达到指定加速度
    StyleSet = LOW;                                    // 状态控制位为低,设置为振动状态
    PulseSet = LOW;                                    // 禁止计数器处于清零状态
    DELAY(15);
    PulseSet = HIGH;
    Select1 = LOW;
    Select2 = HIGH;
//    ResetAcce = 1;                                    // 加速度校准峰值保持电路有效
    P6 |= 0x02;
}     

   //---------------------------------------------------------------------------------
// 此程序用于发送频率数据至CPLD,分两次发送,先发送低八位,再发送高四位,低八位的
// 锁存地址为(A8,A9为11),高八位地址为10
//---------------------------------------------------------------------------------
void SendFrequency(int Fre)
{   
    uchar    HighFre,LowFre;

    Load = LOW;
    HighFre = (uchar)(Fre/100);                                    // 频率高四位BCD码
    LowFre = (uchar)(Fre%100/10*16);                            // 频率低八位BCD码
    LowFre |=Fre%10;
    ADDRPORT |= 0x80;                                            // 低八位频率数据锁存器地址选中
    CPLDDATAPORT = LowFre;                                        // 发送低八位频率数据
    DELAY(2);
    ADDRPORT &= 0x7f;                                            // 频率高四位BCD码
    CPLDDATAPORT = HighFre;                                        // 发送高四位频率数据
    DELAY(2);
    Load = HIGH;   
}

//---------------------------------------------------------------------------------
// 此程序输出脉冲波形,使振动台工作在手动冲击。
//---------------------------------------------------------------------------------
void SinglePulse(void)
{   
    EnableSpeaker = 1;                // 禁止扬声器
//    SendFrequency(Width);            // 将冲击脉宽值转化为频率发送给CPLD
    SendFrequency(15);
//    Pulse_VoltConvert(10);            //2009.06.16.15.34   
    StyleSet = HIGH;                                 // 使振动台工作在冲击状态,同时使计数器清零
    DELAY(20);
    Select1 = HIGH;
    Select2 = LOW;
    PulseSet=LOW;                                    // 产生下降延,完成一个周期的扫描,形成一次冲击
    DELAY(10);
    PulseSet=HIGH;   
}     

//---------------------------------------------------------------------------------
// 此程序将无符号的电压值转变为DA寄存器(12位DA)的值,使二者对应起来
// 应用于冲击状态下  
//---------------------------------------------------------------------------------
void Pulse_VoltConvert(uchar Vol)
{   
    long    DacData;
    long     temp=Vol;
    DacData = temp*4095/(PVREFD);
    temp = (uint)DacData;

    //这段代码改动,原因是da1不好使了,用da0代替之         2008.3.11
    DAC1L = (uchar)temp;
    DAC1H = (uchar)(temp/256);            
}
//---------------------------------------------------------------------------------------
// ADC1初始化配置ADC1使用定时器3溢出作为转换源,ADC1用于测量峰值保持电路输出的冲击加速度电
// 压值
//---------------------------------------------------------------------------------------
void ADC1_Init(void)
{
    ADC1CN = 0x02;                            // 禁止ADC1;正常跟踪模式
                                            // 定时器3溢出启动AD转换
    AMX1SL = 0x00;                            // 配置AIN0.0AD输入
    ADC1CF = (SYSCLK/2500000) << 3;         // ADC 转换时钟=2.5MHz
    ADC1CF |= 0x01;                         // PGA增益=1

    EIE2 |= 0x08;                             // 允许ADC1中断
    EIP2 = 0x08;                            // ADC1中断为高优先级       余加
}

//---------------------------------------------------------------------------------------
// 初始化各变量,赋相应初值
//---------------------------------------------------------------------------------------

//--------------------------------------------------------------------
// SMBus 随机读函数,从给定存储器地址读一个或多个字节
// chip_select = 待读EEPROM的器件从地址0xa0
// uint_address = 待读存储器起始地址(16位)
// length 待读存储器的字节数
//--------------------------------------------------------------------
void SM_Receive (uchar chip_select,uint uint_Address, uchar *p,uchar length)
{
    while (SMBusy);                                     // 等待总线空闲
    SMBusy = 1;                                         //占用SMBus设置为忙
    SMB0CN = 0x44;                                         // 允许SMBus应答周期发ACK
    ByteNumber = length;                                 // 待读字节数
    Command = (chip_select | READ);                     // 器件选择代码+ READ
     AddressT[1] = (uchar)uint_Address;                    // 待写的存储器低8位地址
    AddressT[0] = (uchar)(uint_Address>>8);                // 待写的存储器高8位地址
    Add_HorL_Flag=0;                                    // 先发高8位
    PByte = p;                                             // 待写数据
    STA = 1;                                             // 启动传输过程
    while (SMBusy);                                     // 等待传输结束
}
回复

使用道具 举报

  • TA的每日心情
    开心
    2024-9-7 09:00
  • 签到天数: 2 天

    [LV.1]初来乍到

    0

    主题

    4981

    回帖

    3456

    积分

    二级逆天

    积分
    3456

    终身成就奖社区居民优秀斑竹奖

    QQ
    发表于 2017-11-26 14:38:50 | 显示全部楼层
    谢谢分享上位机波形检测C++
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    论坛开启做任务可以
    额外奖励金币快速赚
    积分升级了


    Copyright ©2011-2024 NTpcb.com All Right Reserved.  Powered by Discuz! (NTpcb)

    本站信息均由会员发表,不代表NTpcb立场,如侵犯了您的权利请发帖投诉

    平平安安
    TOP
    快速回复 返回顶部 返回列表