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

📄 iec101.c

📁 电力变电站RTU监控软件(80C196NT单片机) 遥控
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// 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 + -