📄 iec101.c
字号:
//
// File name =IEC101Link.C //串行通信IEC101Link维护软件规约程序
//设计 何风涛
#include"class.h"
#include "classext.h"
void IEC101LinkTask(struct TIEC101LinkStruct FARDATA *Arg);
void IEC101LinkRx(struct TIEC101LinkStruct FARDATA *Arg);
void IEC101LinkTx(struct TIEC101LinkStruct FARDATA *Arg);
void IEC101LinkCommand(struct TIEC101LinkStruct FARDATA *Arg);
void IEC101LinkComTrans(struct TIEC101LinkStruct FARDATA *Arg);
void Ack(struct TIEC101LinkStruct FARDATA *Arg);
void Nak(struct TIEC101LinkStruct FARDATA *Arg,unsigned char NakNo);
void IEC101LinkSendAFrame(struct TIEC101LinkStruct FARDATA *Arg);
void IEC101LinkRecFile(struct TIEC101LinkStruct FARDATA *Arg);
void IEC101LinkAck(struct TIEC101LinkStruct FARDATA *Arg);
void IEC101LinkNak(struct TIEC101LinkStruct FARDATA *Arg);
char RxdCrc(struct TIEC101LinkStruct FARDATA *Arg);
unsigned int Crc16(unsigned char FARDATA *ptr,int count);
unsigned char FileError(struct TIEC101LinkStruct FARDATA *Arg);
unsigned char RTUStatus(struct TIEC101LinkStruct FARDATA *Arg);
void IEC101LinkTimer(struct TIEC101LinkStruct FARDATA *Arg);
unsigned int readfile(void FARDATA *dbuf,size_t maxl,FILE *fp);
void FileName(struct TIEC101LinkStruct FARDATA *Arg);
void IEC101LinkSendFrame(struct TIEC101LinkStruct FARDATA *Arg);
void IEC101LinkFileSend(struct TIEC101LinkStruct FARDATA *Arg);
void LoadFile(struct TIEC101LinkStruct FARDATA *Arg);
struct TIEC101LinkStruct FARDATA *InitIEC101Link(int ComTaskNo)
{
struct TIEC101LinkStruct FARDATA *Arg;
if((Arg=(struct TIEC101LinkStruct FARDATA *)malloc(sizeof(struct TIEC101LinkStruct)))==NULL)
{
return(NULL);
}
memset(Arg,0,sizeof(struct TIEC101LinkStruct));
Arg->ComTaskNo=ComTaskNo;
Arg->RxdStatus=START;
if((Arg->TxdBuf=(unsigned char FARDATA *)malloc(1024*sizeof(char)))==NULL)
{
return(NULL);
}
Arg->TxdStatus=WAIT;
Arg->Ykcomm=yknull;
Arg->StatusCode=1;
Arg->Letter_from_box=boxnull;
Arg->ReadFlag=0;
Arg->LinkStatus=LinkOFF;
Arg->ComMode=SubStation;
if((Arg->RxdBuf=(unsigned int FARDATA *)malloc(1024*sizeof(int)))==NULL)
{
return(NULL);
}
if((Arg->RecBuf=(unsigned char FARDATA *)malloc(2048*sizeof(char)))==NULL)
{
return(NULL);
}
if((Arg->TrnLetter=(unsigned char FARDATA *)malloc(260*sizeof(char)))==NULL)
{
return(NULL);
}
if((Arg->RecLetter=(unsigned char FARDATA *)malloc(260*sizeof(char)))==NULL)
{
return(NULL);
}
return(Arg);
}
void IEC101Link(struct TIEC101LinkStruct FARDATA *Arg)
{
if(TaskStatus(Arg->ComTaskNo) & 0x02) IEC101LinkRx(Arg); // Rx Task
if(TaskStatus(Arg->ComTaskNo) & 0x01) IEC101LinkTx(Arg); // Tx Task
if(TaskStatus(Arg->ComTaskNo) & 0x80) IEC101LinkTimer(Arg);// 定时监视
}
unsigned char SFrameCS(struct TIEC101LinkStruct FARDATA *Arg)
{/* 固定帧格式校验 */
unsigned char ch,cs;
cs=0xff;
switch(Arg->FrameStatus)
{
case 0x10:Arg->RxdBufLength=Tgets(Arg->ComTaskNo,4,Arg->RxdBuf);
if(Arg->RxdBufLength==4)
{
Arg->LinkControl=(*(Arg->RxdBuf+0));
Arg->Linkadr= (*(Arg->RxdBuf+1));
Arg->LinkCS= (*(Arg->RxdBuf+2));
Arg->LinkEnd= (*(Arg->RxdBuf+3));
if(Arg->LinkEnd==0x16)
{
ch=Arg->LinkControl+Arg->Linkadr;
if(ch==Arg->LinkCS) cs=0;
}
}
break;
case 0x68:Arg->RxdBufLength=Tgets(Arg->ComTaskNo,5,Arg->RxdBuf);
if(Arg->RxdBufLength==5)
{
Arg->RxdFrameLength=(*(Arg->RxdBuf+0));
if(Arg->RxdFrameLength==(*(Arg->RxdBuf+1)))
{
if(Arg->RxdFrameLength>=2)
{
if((*(Arg->RxdBuf+2))==0x68)
{
Arg->LinkControl=(*(Arg->RxdBuf+3));
Arg->Linkadr= (*(Arg->RxdBuf+4));
cs=0;
}
}
}
}
break;
}
return cs;
}
void HFrameAct(struct TIEC101LinkStruct FARDATA *Arg)
{/* 帧处理 */
union WTEMP_ST T;
T.Word=(UINT)Tgetc(Arg->ComTaskNo);
switch(Arg->FrameStatus)
{
case 0x10:if(SFrameCS(Arg))
{/* 接收错误 */
return;
}
Arg->TrnLetter[0]=8; //长度
Arg->TrnLetter[1]=Arg->UpTaskNo; //目的任务号
Arg->TrnLetter[2]=Arg->TaskNo; //源任务号
Arg->TrnLetter[3]=0; //帧状态
Arg->TrnLetter[4]=0x00; //固定帧
Arg->TrnLetter[5]=0x00; //帧长度
Arg->TrnLetter[6]=Arg->LinkControl;//控制帧
Arg->TrnLetter[7]=Arg->Linkadr; //链路域地址
if(TWrite(Arg->TrnLetter))
{
}else
{
Nak(Arg,11); //链路忙
}
break;
case 0x68:if(SFrameCS(Arg))
{/* 接收错误 */
return;
}
if(Arg->RxdFrameLength==2)
{
Arg->TrnLetter[0]=8; //长度
Arg->TrnLetter[1]=Arg->UpTaskNo; //目的任务号
Arg->TrnLetter[2]=Arg->TaskNo; //源任务号
Arg->TrnLetter[3]=0; //帧状态
Arg->TrnLetter[4]=0x80; //可变帧
Arg->TrnLetter[5]=0x00; //帧长度
Arg->TrnLetter[6]=(*(Arg->RxdBuf+5)); //控制帧
Arg->TrnLetter[7]=(*(Arg->RxdBuf+6)); //链路域地址
if(TWrite(Arg->TrnLetter))
{
}else
{
Nak(Arg,11); //链路忙
}
return;
}
if((Arg->RxdFrameLength+5-Arg->RxdBufLength)<=128) ChangeProWarn(Arg->TaskNo,0,Arg->RxdFrameLength+5-Arg->RxdBufLength);
else ChangeProWarn(Arg->TaskNo,0,128);
Arg->RxdStatus=FRAME;
break;
default: break;
}
}
void IEC101LinkRx(struct TIEC101LinkStruct FARDATA *Arg)
{
unsigned char ch;
struct TComStruct FARDATA *Com;
union WTEMP_ST T;
Com=(struct TComStruct *)Task[Arg->ComTaskNo].DevPtr;//设备驱动表指针
T.Word=(UINT)Tgetc(Arg->ComTaskNo);
if(T.B.High!=0)
{/* 接收错误 */
return;
}
/*-------------- Receive start ------------------------------------*/
if(Arg->RxdStatus==START)
{
switch(T.B.Low)
{
case 0x10: ChangeProWarn(Arg->ComTaskNo,RXD_BUF_PRO,4);
Arg->RxdStatus=HEAD;
Arg->FrameStatus=0x10;
break;
case 0x68: ChangeProWarn(Arg->ComTaskNo,RXD_BUF_PRO,5);
Arg->RxdStatus=HEAD;
Arg->FrameStatus=0x68;
break;
default:Tgets(Arg->ComTaskNo,255,Arg->RxdBuf);
Arg->RxdBufLength=0;
return;
break;
}
}
/*------------------Receive head-----------------------------------*/
if((Arg->RxdStatus==HEAD)&&(TaskStatus(Arg->ComTaskNo) & 0x02))
{
HFrameAct(Arg);
}
/*---------------------Receive frame-----------------------------------*/
if((Arg->RxdStatus==FRAME) && (TaskStatus(Arg->ComTaskNo) & 0x02))
{
if((Arg->RxdFrameLength+5-Arg->RxdBufLength)<=128)
{
Arg->RxdBufLength +=Tgets(Arg->ComTaskNo,Arg->RxdFrameLength+5,(Arg->RxdBuf+Arg->RxdBufLength));
}else
{
Arg->RxdBufLength +=Tgets(Arg->ComTaskNo,128,(Arg->RxdBuf+Arg->RxdBufLength));
}
if(Arg->RxdBufLength >=(Arg->RxdFrameLength+5))
{
Arg->TrnLetter[0]=Arg->RxdFrameLength+5; //长度
Arg->TrnLetter[1]=Arg->UpTaskNo; //目的任务号
Arg->TrnLetter[2]=Arg->TaskNo; //源任务号
Arg->TrnLetter[3]=0; //帧状态
Arg->TrnLetter[4]=0x80; //可变帧
Arg->TrnLetter[5]=Arg->RxdFrameLength; //帧长度
for(i=0;i<Arg->RxdFrameLength;i++)
{
Arg->TrnLetter[6+i]=(*(Arg->RxdBuf+5+i));
}
if(TWrite(Arg->TrnLetter))
{
}else
{
Nak(Arg,11); //链路忙
}
return;
};
if(Arg->RxdFrameLength+5-Arg->RxdBufLength<=128) ChangeProWarn(Arg->ComTaskNo,0,Arg->RxdFrameLength-Arg->RxdBufLength+5);
else ChangeProWarn(Arg->ComTaskNo,0,128);
return;
};
}
void IEC101LinkCommand(struct TIEC101LinkStruct FARDATA *Arg)
{
if(Arg->RxdBufLength>1024)
{
Tgets(Arg->ComTaskNo,255,Arg->RxdBuf);
Arg->RxdBufLength=0;
Arg->RxdStatus=START;
ChangeProWarn(Arg->ComTaskNo,0,1);
if(FileError(Arg)) Nak(Arg,1); // Receive Data error
return;
};
if(!RxdCrc(Arg)) // if CRC check error,clear RXD buffer;
{
Tgets(Arg->ComTaskNo,255,Arg->RxdBuf);
Arg->RxdBufLength=0;
Arg->RxdStatus=START;
ChangeProWarn(Arg->ComTaskNo,0,1);
if(FileError(Arg)) Nak(Arg,0x1); // Receive Data error
}else IEC101LinkComTrans(Arg);
ChangeProWarn(Arg->ComTaskNo,0,1);
Arg->RxdStatus=START;
}
char RxdCrc(struct TIEC101LinkStruct FARDATA *Arg)
{
unsigned int i,Length;
Length=(unsigned char)*(Arg->RxdBuf)+(unsigned char)*(Arg->RxdBuf+1)*256+7;
for(i=0;i<Length;i++)
{
*(Arg->RecBuf+i)=*(Arg->RxdBuf+i);
};
Length-=2;
i=Crc16((unsigned char FARDATA *)Arg->RecBuf,Length);
if(i==(*(Arg->RecBuf+Length+1)*256+*(Arg->RecBuf+Length))) return(0xff);
else return(0);
}
unsigned int Crc16(unsigned char FARDATA *ptr,int count)
{
unsigned int crc, i;
crc = 0;
while (--count >= 0)
{
crc = (crc ^ (((int)*ptr++) << 8));
for (i = 0; i < 8; ++i) if (crc & 0x8000) crc = ((crc << 1) ^ 0x1021);
else crc = crc << 1;
}
return (crc & 0xFFFF);
}
void IEC101LinkTx(struct TIEC101LinkStruct FARDATA *Arg)
{
unsigned char Num,OldNum;
if(Arg->TxdStatus==WAIT)
{
StopTxd(Arg->ComTaskNo);
return;
};
if((Arg->TxdBufLength - Arg->TxdPtr) <= 255) Num=Arg->TxdBufLength - Arg->TxdPtr;
else Num=255;
OldNum=Num;
Tputs(Arg->ComTaskNo,&Num,(char FARDATA *)(Arg->TxdBuf+Arg->TxdPtr));
Arg->TxdPtr +=OldNum-Num;
if(Arg->TxdBufLength<=Arg->TxdPtr) Arg->TxdStatus=WAIT;
}
void Ack(struct TIEC101LinkStruct FARDATA *Arg)
{
*(Arg->TxdBuf)=0;
*(Arg->TxdBuf+1)=0;
*(Arg->TxdBuf+2)=0x06;
*(Arg->TxdBuf+3)=0;
*(Arg->TxdBuf+4)=RTUStatus(Arg);
IEC101LinkSendAFrame(Arg);
}
void Nak(struct TIEC101LinkStruct FARDATA *Arg,unsigned char NakNo)
{
*(Arg->TxdBuf+0)=2;
*(Arg->TxdBuf+1)=0;
*(Arg->TxdBuf+2)=21;
*(Arg->TxdBuf+3)=NakNo;
*(Arg->TxdBuf+4)=RTUStatus(Arg);
*(Arg->TxdBuf+5)=*(Arg->RecBuf+2);
*(Arg->TxdBuf+6)=*(Arg->RecBuf+3);
IEC101LinkSendAFrame(Arg);
}
void IEC101LinkSendAFrame(struct TIEC101LinkStruct FARDATA *Arg)
{
int Length;
unsigned int Sum;
unsigned char Count;
unsigned char FARDATA *Frame;
unsigned int Crc;
unsigned int i;
Frame=Arg->TxdBuf;
Length=(*Frame+*(Frame+1)*256+5);
Sum=Length;
if(!(*(Arg->TxdBuf+3)&0x80))
{
Crc = 0;
while(--Length >= 0)
{
Crc = (Crc ^ (((int)*(Frame++)) << 8));
for (i = 0; i < 8; ++i)
if (Crc & 0x8000) Crc = ((Crc << 1) ^ 0x1021);
else Crc = Crc << 1;
};
Crc &= 0xFFFF;
*(Arg->TxdBuf+Sum)=Crc;
*(Arg->TxdBuf+Sum+1)=Crc>>8;
};
Sum += 2;
Tputc(Arg->ComTaskNo,1); //01H
ChangeProWarn(Arg->ComTaskNo,1,Sum);
SetTimer(Arg->ComTaskNo,0);
if(Sum >255) Count=255;
else Count=Sum;
Arg->TxdPtr=Count;
Tputs(Arg->ComTaskNo,&Count,(char FARDATA *)Arg->TxdBuf);
Arg->TxdBufLength=Sum;
Arg->TxdPtr -=Count;
if(Arg->TxdBufLength>Arg->TxdPtr) Arg->TxdStatus=SEND;
}
void IEC101LinkComTrans(struct TIEC101LinkStruct FARDATA *Arg)
{
unsigned int i;
// if(*(Arg->RecBuf+4)&0x02)//设备状态.D1=1 上装参数通讯失败
// for(i=0;i<Arg->YCDNUM;i++) Arg->MYC[Arg->YCDNO[j]]=Arg->MYCtemp[j];
if(*(Arg->RecBuf+4)&0x80) //设备状态.D7=1
{
*(Arg->TxdBuf+3)|=0x80;//R是通讯出错传送标志,“1”表示该帧为重传的帧
IEC101LinkSendAFrame(Arg);
return;
};
switch(*(Arg->RecBuf+2)) //功能码
{
case 1:IEC101LinkRecFile(Arg); //文件传送
break;
case 2://遥测查询
break;
case 3://遥信查询
break;
case 4://电度查询
break;
case 5://事项顺序记录查询
break;
case 6://ACK对无需应答帧的确认,如分组传送中。
break;
case 7://trnsmit system status to notebook 系统状态
break;
case 8://yk operate 遥控操作
break;
case 10://高速采样
break;
case 11://reset 系统复位
Arg->TxdCode=0;
SystemReset();
break;
case 15://transparent data 透明数据传送
break;
case 16://时间
break;
case 17://变量查询
break;
case 18://故障录波
break;
case 21://NAK对接收错误帧的回执
break;
case 22://make system config file
break;
case 30://complex data packet 召唤全数据/召唤遥信遥测报文
break;
case 31://changed yc and yx 召唤变化数据数据报文
break;
default:if(FileError(Arg)) Nak(Arg,0);
break;
};
}
void IEC101LinkRecFile(struct TIEC101LinkStruct FARDATA *Arg) //文件传送
{
unsigned int i;
unsigned char command[64];
union WTEMP_ST T;
switch(*(Arg->RecBuf+3))
{
case 0://写方式打开文件(下装文件)
/* command[0]='\0';
strcpy((char FARDATA *)Arg->RecName,(char FARDATA *)(Arg->RecBuf+5));
strcat((char FARDATA *)command,(char FARDATA *)Arg->RecName);//串连接
fclose(Arg->fp);
if ((Arg->fp=fopen(command, "wb"))== NULL)
{
Nak(Arg,3);// Send File Nak for file open error
Arg->RxdCode=0;//NOUSE
}else
{//Send File Ack for file open OK with write mode;
Ack(Arg);
Arg->RxdPacketNo=0;
Arg->FileLength=0;
for(i=36;i>=33;i--)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -