|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区
您需要 登录 才可以下载或查看,没有账号?立即注册
×
//--------------------------------------------------------------------
-----------------------------------------------------------------------------------
#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&0xdf 4 = 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> ARTICLENUM) // 如果微粒碰撞的次数超过一定值,说明多余物较明显,点亮失效指示灯。
{
ENABLEFAILLED;
bIsParticleFlag = TRUE; // 说明检测到多余物
}
}
*/
// }
Key(); // 键盘服务程序
if(Particle==0&&bShockCommand==0)
{
ENABLEDETLED; // 如果检测到噪声超限且当前并没有执行冲击指令,点亮噪声超限指示灯
ucParticleNum++; // 次数加1
}
else DISABLEDETLED;
/*if(CommandType==0x01) // 全速运行执行相应的方案
{
if(Particle==0&&bShockCommand==0) // 检测到微粒且并没有执行冲击指令,说明器件中含有多余物。
{
if(ucParticleNum> ARTICLENUM) // 如果微粒碰撞的次数超过一定值,说明多余物较明显,点亮失效指示灯。
{
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< eakCountNUM;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); // 等待传输结束
} |
|