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

📄 link101.c

📁 电力变电站RTU监控软件(80C196NT单片机) 遥控
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// File name =IEC101Link.C	//串行通信IEC101Link维护软件规约程序
//设计 何风涛
#include"class.h"
#include"classext.h"

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->TaskNo=ComTaskNo+UPOffset;

       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)
{
//   fft_reg[0]++;
//   fft_reg[1]=TaskStatus(Arg->ComTaskNo);
//   if(TaskStatus(Arg->ComTaskNo) & 0x02) IEC101LinkRx(Arg);	 // Rx Task
//   if(TaskStatus(Arg->ComTaskNo) & 0x01) IEC101LinkTx(Arg);	 // Tx Task
     if(TaskStatus(Arg->TaskNo) & 0x20) IEC101LinkLetter(Arg);// Mail
//   if(TaskStatus(Arg->TaskNo) & 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)
{/*  帧处理  */
     unsigned char  ch,chh;
     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[5]=0x00;	    //帧长度
		 Arg->TrnLetter[6]=Arg->LinkControl;//控制帧
		 Arg->TrnLetter[7]=Arg->Linkadr;    //链路域地址
		 IEC101LinkRxFrameType(Arg);//Arg->TrnLetter[4]=type;//功能码
		 if(TWrite(Arg->TrnLetter))
		 {


		 }else
		 {
//		     Nak(Arg,11); //链路忙
		 }
		 break;
       case 0x68:if(SFrameCS(Arg))
		 {/*  接收错误	  */

		    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 int   ui;
     unsigned char ch;
     struct TComStruct FARDATA	 *Com;
     union	    WTEMP_ST	 T;
     Com=(struct TComStruct *)Task[Arg->ComTaskNo].DevPtr;//设备驱动表指针
     T.Word=(UINT)Tgetc(Arg->ComTaskNo);
//   fft_reg[2]++;
     if(T.B.High!=0)
     {/*  接收错误    */
//     fft_reg[3]++;
       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;
//			   fft_reg[4]++;
			   break;
	       case  0x68: ChangeProWarn(Arg->ComTaskNo,RXD_BUF_PRO,5);
			   Arg->RxdStatus=HEAD;
			   Arg->FrameStatus=0x68;
//			   fft_reg[5]++;
			   break;
		   default:Tgets(Arg->ComTaskNo,255,Arg->RxdBuf);
			   Arg->RxdBufLength=0;
//			   fft_reg[6]++;
			   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(ui=0;ui<Arg->RxdFrameLength;ui++)
	    {
		Arg->TrnLetter[6+ui]=(*(Arg->RxdBuf+5+ui));
	    }
	    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 IEC101LinkLetter(struct TIEC101LinkStruct FARDATA *Arg)
{
  unsigned char  ch;
  if(TRead(Arg->TaskNo,Arg->RecLetter))
  {
     switch(Arg->RecLetter[4]) //code
     {
       case   C_RQ_NA_1_LNKREQ:      /* 请求链路状态	 */
				     *(Arg->TxdBuf+0 )=0x10;
				     if(Arg->ComMode==HostStation)
				     {
					ch=Arg->RecLetter[5];
					ch=ch & 0x7f; //DIR=0 主站向子站传输
					ch=ch | 0x40; //PRM=1 主站向子站传输主站为启动站
					if(Arg->FCB==0)  ch=ch & 0xdf;
					    else	 ch=ch | 0x20;
					ch=ch & 0xef;
					ch=ch+0x09;   //帧类型=请求响应帧
				     }else
				     {


				     }
				     *(Arg->TxdBuf+1)=ch;
				     *(Arg->TxdBuf+2)=Arg->RecLetter[6];
				     IEC101LinkSendAFrame(Arg);
				     break;
       case   M_RQ_NA_1_LNKREQ:      /* 链路状态响应帧	 */
				     break;
       case   C_RL_NA_1_SEND:	     /* 复位远方链路	 */
				     break;
       case   M_RL_NA_1_CON:	     /* 复位远方链路确认帧 */
				     break;
       case   M_BY_NA_1:	     /* 忙帧  */
				     break;
       case   M_NV_NA_1:	     /* 无所请求的数据帧 */
				     break;
       case   C_P1_NA_1:	     /* 召唤1级数据 */
				     break;
       case   C_P2_NA_1:	     /* 召唤2级数据 */
				     break;
       case   C_PA_NA_1:	     /* 召唤要求访问位的请求帧 */
				     break;
       case   C_PA_NA_1RES:	     /* 召唤要求访问位的响应帧 */
				     break;
       case   C_RP_NA_1ACT:	     /* 复位远动终端发送帧 */
				     break;
       case   C_RP_NA_1ACTCON:	     /* 复位远动终端确认帧 */
				     break;
       case   C_IC_NA_1ACT:	     /* 总召唤命令帧 */
				     break;
       case   C_IC_NA_1ACTCON:	     /* 总召唤确认帧 */
				     break;
       case   M_IC_NA_1ACTTERM:      /* 总召唤结束帧 */
				     break;
       case   C_IC_NA_1CYCLICACT:    /* 分组召唤发送帧 */
				     break;
       case   C_IC_NA_1CYCLICACTCON: /* 分组召唤响应帧 */
				     break;
       case   M_RL_NA_1:	     /* 主站初始化结束响应帧 */
				     break;
       case   M_EI_NA_1:	     /* 子站初始化结束帧 */
				     break;
       case   M_ME_NA_1CYCLIC:	     /* 带品质描述的遥测帧 */
				     break;
       case   M_ME_ND_1CYCLIC:	     /* 不带品质描述的遥测帧 */
				     break;
       case   M_SP_NA_1CYCLIC:	     /* 单点遥信帧 */
				     break;
       case   M_DP_NA_1CYCLIC:	     /* 双点遥信帧 */
				     break;
       case   M_ST_NA_1CYCLIC:	     /* 变压器分接头帧 */
				     break;
       case   M_BO_NA_1CYCLIC:	     /* 远动终端状态帧 */
				     break;
       case   M_BD_NA_1CYCLIC:	     /* BCD码响应帧 */
				     break;
       case   C_CS_NA_1ACT:	     /*时钟同步发送帧 */
				     break;
       case   C_CS_NA_1ACTCON:	     /*时钟同步确认帧 */
				     break;
       case   M_ME_NA_1SPONT:	     /*带品质描述的遥测数据变化响应帧 */
				     break;
       case   M_ME_ND_1SPONT:	     /*不带品质描述的遥测数据变化响应帧 */
				     break;
       case   M_ME_TA_1SPONT:	     /*带时标的遥测数据变化响应帧 */
				     break;
       case   M_ST_NA_1SPONT:	     /* 变压器分接头变化响应帧 */
				     break;
       case   M_BD_NA_1SPONT:	     /*BCD码变化响应帧 */
				     break;
       case   M_SP_TA_1:	     /* 单点信息事件顺序记录帧 */
				     break;
       case   M_DP_TA_1:	     /* 双点信息事件顺序记录帧 */
				     break;
       case   M_EP_TA_1:	     /* 继电器保护装置单点信息事件顺序记录帧 */
				     break;
       case   M_EP_TB_1:	     /* 继电器保护装置 成组启动事件顺序记录帧 */
				     break;
       case   M_EP_TC_1:	     /* 继电器保护装置 成组输出电路事件顺序记录帧 */
				     break;
       case   M_ST_TA_1:	     /* 带时标的步位置信息(变压器分接头)帧*/
				     break;
       case   M_SP_NA_1SPONT:	     /* 单点信息状态变位帧 */
				     break;
       case   M_DP_NA_1SPONT:	     /* 双点遥信变位帧 */
				     break;
       case   M_PS_NA_1SPONT:	     /* 状态和状态变位的遥信帧 */
				     break;
       case   M_BO_NA_1SPONT:	     /* 远动终端状态变化帧 */
				     break;
       case   M_DATA_NA_1SPONT:      /* 由主站的读命令形成的1级用户数据帧 */
				     break;
       case   C_DC_NA_1ACT:	     /* 遥控选择命令 发送帧 */
				     break;
       case   C_DC_NA_1ACTCON:	     /* 遥控选择命令 确认帧 */
				     break;
       case   C_DC_NA_1DEACT:	     /* 遥控撤消命令 发送帧 */
				     break;
       case   C_DC_NA_1DEACTCON:     /* 遥控撤消命令 确认帧 */
				     break;
       case   C_DC_NA_1EXCO:	     /* 遥控执行命令 发送帧 */
				     break;
       case   C_DC_NA_1EXCOCON:      /* 遥控执行命令 确认帧 */
				     break;
       case   C_SE_NA_1ACT:	     /* 设点命令 发送帧 */
				     break;
       case   C_SE_NA_1ACTCON:	     /* 设点命令 确认帧 */
				     break;
       case   C_CI_NA_1ACT:	     /* 冻结和召唤电能脉冲 发送帧 */
				     break;
       case   C_CI_NA_1ACTCON:	     /* 冻结和召唤电能脉冲 确认帧 */
				     break;
       case   M_IT_NA_1CYCLIC:	     /* 电能脉冲计数量响应帧 */
				     break;
       case   M_IT_TA_1CYCLIC:	     /* 带时标电能脉冲计数量响应帧 */
				     break;
       case   C_CI_NA_1ACTTERM:      /* 电能脉冲计数量结束帧 */
				     break;
       case   C_CI_NA_TACT:	     /* 分组召唤电能脉冲计数量请求帧 */
				     break;
       case   M_IT_NA_1:	     /* 分组召唤电能脉冲计数量响应帧 */
				     break;
       case   M_IT_TA_1:	     /* 分组带时标电能脉冲计数量响应帧 */
				     break;
       case   P_ME_NA_1ACT:	     /* 设置参数的发送帧 */
				     break;
       case   P_ME_NA_1CON:	     /* 设置参数的确认帧 */
				     break;
       case   P_AC_NA_1ACT:	     /* 设置激活的发送帧 */
				     break;
       case   P_AC_NA_1CON:	     /* 设置激活的确认帧 */
				     break;
       case   C_TS_NA_1ACT:	     /* 测试通道发送帧	 */
				     break;
       case   C_TS_NA_1ACTCON:	     /* 测试通道的确认帧 */
				     break;
       case   C_RD_NA_1ACT:	     /* 读数据命令发送帧 */
				     break;
       case   M_CON_NA_1ACTCON:      /* 读数据命令响应帧 */
				     break;
       case   F_SC_NA_1ACT:	     /* 召唤文件、目录、节和文件选择命令 */
				     break;
       case   F_DR_TA_1ACTCON:	     /* 目录响应帧 */
				     break;
       case   F_FR_NA_1ACTCON:	     /* 文件准备好确认帧 */
				     break;
       case   F_SR_NA_1ACTCON:	     /* 节准备好确认帧 */
				     break;
       case   F_SG_NA_1ACTCON:	     /* 段的响应帧 */
				     break;
       case   F_LS_NA_1ACTCON:	     /* 最后节、最后段的确认帧 */
				     break;
       case   F_AF_NA_1ACTCON:	     /* 文件、节的确认帧 */
				     break;
	      default:		     break;
     }
  }
}

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 IEC101LinkSendAFrame(struct TIEC101LinkStruct FARDATA *Arg)
{
   int Length,i;
   unsigned char Count;
   unsigned int  Sum;
   unsigned char ch,chsum;
   ch=*(Arg->TxdBuf+0);
   if(ch==0x10)
   {
      chsum=*(Arg->TxdBuf+1);
      chsum=*(Arg->TxdBuf+2)+chsum;
      *(Arg->TxdBuf+3)=chsum;
      *(Arg->TxdBuf+4)=0x16;
      Sum=5;
   }else
   {
      Length=*(Arg->TxdBuf+1);
      chsum=0;
      for(i=0; i< Length; i++)
      {
	 chsum=chsum+*(Arg->TxdBuf+4+i);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -