📄 link101.c
字号:
//
// 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 + -