📄 secdlink.c
字号:
#include "includes.h"
#include "iec101def.h"
#include "iec101wh.h"
#include "secdlink.h"
#include "secapp.h"
extern struct LinkInfo* ComLink[PORTNUM];
extern struct AppInfo* ComApp[PORTNUM];
extern struct SysPort* ComDb[PORTNUM];
BOOL Init101SecDLink(INT8U Port, struct PortAppInfo* PortCfg)
{
INT8U i;
struct PSec101_2002Pad *pPad;
i = Port - 1;
pPad = (struct PSec101_2002Pad*)(PortCfg->pPad);
ComLink[i]->Baudrate = PortCfg->Baudrate;
if (pPad!=NULL)
{
ComLink[i]->TimeOutValue = pPad->PBase.Timer.TimeoutValue1;
if (ComLink[i]->TimeOutValue<100)
ComLink[i]->TimeOutValue=100;
ComLink[i]->DLIdleTime=ComLink[i]->TimeOutValue/100;//线路空闲检测时间不能小于2秒
if(ComLink[i]->DLIdleTime<2)
ComLink[i]->DLIdleTime=2;
if(pPad->PBase.ProtocolControl&BALANCE)
{
ComLink[i]->BalanMode=TRUE;
ComLink[i]->IEC_DIR=0x80;
}
else
{
ComLink[i]->BalanMode=FALSE;
ComLink[i]->IEC_DIR=0;
}
ComLink[i]->LinkAddrSize=pPad->LINKAddrSize;
if(ComLink[i]->LinkAddrSize!=1)
ComLink[i]->LinkAddrSize=2;//zzw
}
else
{
ComLink[i]->TimeOutValue=100;
ComLink[i]->BalanMode=FALSE;
ComLink[i]->LinkAddrSize=2;
}
ComLink[i]->DLPriStatus=PRIDISABLE;
ComLink[i]->SourceNo = ComDb[i]->DBCfgs->Address;
ComLink[i]->FlagData1=FALSE;
ComLink[i]->TxdStatus=TXDSEND;
ComLink[i]->RxdStatus=RXDSTART;
ComLink[i]->FrameHead=0;
ComLink[i]->TxdHead=0;
ComLink[i]->TxdTail=0;
ComLink[i]->RxdHead=0;
ComLink[i]->RxdTail=0;
ComLink[i]->RxdLength=0;
ComLink[i]->StartDL=0xff;
ComLink[i]->RemoteDLOK=0;
ComLink[i]->LocalDLOK=0;
ComLink[i]->LastControl=0xff;
ComLink[i]->TimeOutTick=ComLink[i]->TimeOutTick_Pri=ComLink[i]->TimeOutTick_Sec=ComLink[i]->TimeOutTickCopy=0;
if(ComLink[i]->LinkAddrSize==1)
ComLink[i]->FixFrmLength=5;
else
ComLink[i]->FixFrmLength=6;
return TRUE;
}
//读MISI数据
void S101RecMISIData(INT8U Port, BOOL Flag)
{
INT16U i, count;
i = Port - 1;
if(ComLink[i]->RxdHead < ComLink[i]->RxdTail) //接收缓冲区中有尚未处理的数据
{
if (ComLink[i]->RxdHead!=0)
{
memcpy(ComLink[i]->RxdBuf,ComLink[i]->RxdBuf+ComLink[i]->RxdHead,ComLink[i]->RxdTail-ComLink[i]->RxdHead);//将未处理的数据移到缓冲区头
ComLink[i]->RxdTail-=ComLink[i]->RxdHead;
ComLink[i]->RxdHead=0;
}
}
else
ComLink[i]->RxdHead=ComLink[i]->RxdTail=0;
// count=0;
count=Readx((INT8U *)&ComLink[i]->RxdBuf[ComLink[i]->RxdTail], LPDUSIZE, Port);
lseek(i+1, count);
if (count>0)
{
ComLink[i]->RxdTail+=count;
S101_2002SearchFrame(Port);
}
}
//发送缓冲区中的数据,写MISI接口
BOOL S101_2002SendDataToMISI(INT8U Port)
{
INT16U SendLen, i, num;
INT8U err;
i = Port - 1;
ComLink[i]->IdleTimeCount = 0;
if (ComLink[i]->TxdStatus==TXDSEND)//新数据发送
{
ComLink[i]->TxdHead=0;
num = ComLink[i]->TxdTail - ComLink[i]->TxdHead;
SendLen = WriteX((INT8U *)&ComLink[i]->TxdBuf[ComLink[i]->TxdHead], num, Port);
ComLink[i]->TxdHead += SendLen;
if (SendLen>0)//数据正常发送(完没完还未判断)
ComLink[i]->TxdStatus=TXDWAIT;
}
else//上次数据未发送完,
SendLen = WriteX(ComLink[i]->TxdBuf+ComLink[i]->TxdHead, ComLink[i]->TxdTail-ComLink[i]->TxdHead, Port);
ComLink[i]->TxdHead+=SendLen;
if(ComLink[i]->TxdHead>=ComLink[i]->TxdTail)//该次任务数据已经发完。
{
ComLink[i]->TxdStatus=TXDSEND;
if(ComLink[i]->BalanMode)
//eventSend(taskIdSelf(),SENDOVER);
OSFlagPost(ComDb[i]->Event, SENDOVER, OS_FLAG_SET, &err);
return TRUE;
}
else
return FALSE;
}
void SecSendPriDataToMISI(INT8U Port)//
{
INT8U i;
i = Port-1;
if (ComLink[i]->TxdStatus==TXDSEND)
ComLink[i]->TxdTail=0;
ComLink[i]->FrameHead=ComLink[i]->TxdTail;
memcpy(ComLink[i]->TxdBuf+ComLink[i]->FrameHead,ComLink[i]->TxdBuf_Pri,ComLink[i]->TxdTail_Pri);
ComLink[i]->TxdTail+=ComLink[i]->TxdTail_Pri;
S101_2002SendDataToMISI(Port);
}
void SendSec101_2002DataToMISI(INT8U Port)//
{
INT8U i;
i=Port-1;
if (ComLink[i]->TxdStatus==TXDSEND)
ComLink[i]->TxdTail=0;
ComLink[i]->FrameHead=ComLink[i]->TxdTail;
memcpy(ComLink[i]->TxdBuf+ComLink[i]->FrameHead,ComLink[i]->TxdBuf_Sec,ComLink[i]->TxdTail_Sec);
ComLink[i]->TxdTail+=ComLink[i]->TxdTail_Sec;
S101_2002SendDataToMISI(Port);
}
void TimeOutFun(INT8U Port, INT8U FailType, INT8U Prm)//超时处理
{
INT8U i;
i = Port-1;
if(!ComLink[i]->RetryCount)
return;
ComLink[i]->RetryCount--;
if(ComLink[i]->RetryCount)
{
if(Prm)//启动站报文超时未收到应答
{
SecSendPriDataToMISI(Port);
ComLink[i]->TimeOutTick_Pri=ComLink[i]->TimeOutTickCopy;
}
else//这里其实运行不到
{
SendSec101_2002DataToMISI(Port);
ComLink[i]->TimeOutTick_Sec=ComLink[i]->TimeOutTickCopy;
}
return;
}
else//超过重发次数后,重新建立链路,并通知应用层。
{
if(ComLink[i]->BalanMode)
{
CallDLStatus(Port);
ComLink[i]->LocalDLOK=0;
ComApp[i]->DLCommand=DL_LINKDISABLE;
ComApp[i]->LengthIn=0;
Sec101_2002AppProc(Port, ComLink[i]->RxdBuf+5+ComLink[i]->LinkAddrSize,ComApp[i]->LengthIn,ComApp[i]->DLCommand,
ComLink[i]->TxdBuf+5+ComLink[i]->LinkAddrSize,(INT16U *)&ComApp[i]->LengthOut,(INT16U *)&ComApp[i]->AppCommand);
S101_2002DLSendProc(Port);
}
}
}
//启动链路过程
void CallDLStatus(INT8U Port)
{
INT8U i;
i=Port-1;
EditFra10(Port, DLREQSTATUS);
S101_2002SendDataToMISI(Port);
ComLink[i]->DLPriStatus=PRIWAITSTATUS;
ComLink[i]->TimeOutTick_Pri=TimeDelay(Port, 2* ComLink[i]->FixFrmLength);
ComLink[i]->RetryCount=MAXRETRYNUM;
if(ComLink[i]->BalanMode)//平衡模式,启动远方链路过程。重新建立链路
{
ComLink[i]->StartDL=0xFF;
ComLink[i]->RemoteDLOK=0;
}
}
void S101_2002SearchFrame(INT8U Port)
{
BOOL Stop=FALSE;
INT8U length,i,err;
i=Port-1;
while ((ComLink[i]->RxdHead < ComLink[i]->RxdTail)&&(!Stop))
{
if(ComLink[i]->RxdStatus==RXDSTART)
{
while ((ComLink[i]->RxdBuf[ComLink[i]->RxdHead]!=STARTCODE68)
&&(ComLink[i]->RxdBuf[ComLink[i]->RxdHead]!=STARTCODE10)
&&(ComLink[i]->RxdHead < ComLink[i]->RxdTail))
{
ComLink[i]->RxdHead++;
}
if (ComLink[i]->RxdHead<ComLink[i]->RxdTail)//找到启动字符,并将报文与缓冲区对齐。
{
ComLink[i]->RxdStatus=RXDHEAD;
if (ComLink[i]->RxdHead!=0)
{
memcpy(ComLink[i]->RxdBuf,ComLink[i]->RxdBuf+ComLink[i]->RxdHead,ComLink[i]->RxdTail-ComLink[i]->RxdHead);
ComLink[i]->RxdTail-=ComLink[i]->RxdHead;
ComLink[i]->RxdHead=0;
}
}
}
ComLink[i]->RxdLength=ComLink[i]->RxdTail-ComLink[i]->RxdHead;
if(ComLink[i]->RxdStatus==RXDHEAD)//报文够一帧则
{
switch (ComLink[i]->RxdBuf[ComLink[i]->RxdHead])
{
case STARTCODE68:
if (ComLink[i]->RxdLength>=5+ComLink[i]->LinkAddrSize)//启动字符到链路地址共6字节。
{
if (!S101_2002ExeDLFun68(Port))//判断是否报文头
{
ComLink[i]->RxdHead++;
ComLink[i]->RxdStatus=RXDSTART;
}
else
ComLink[i]->RxdStatus=RXDCONTINUE;
}
else
Stop=TRUE;
break;
case STARTCODE10:
if (ComLink[i]->RxdLength>=4+ComLink[i]->LinkAddrSize)
{
if (!S101_2002ExeDLFun10(Port))
{
ComLink[i]->RxdHead++;
ComLink[i]->RxdStatus=RXDSTART;
}
else
ComLink[i]->RxdStatus=RXDCONTINUE;
}
else
Stop=TRUE;
break;
}
}
if(ComLink[i]->RxdStatus==RXDCONTINUE)
{
switch (ComLink[i]->RxdBuf[ComLink[i]->RxdHead])
{
case STARTCODE68:
length=ComLink[i]->RxdBuf[ComLink[i]->RxdHead+1];
if (ComLink[i]->RxdLength>=length+6)//报文收全,进行处理
{
if ( (ComLink[i]->RxdBuf[ComLink[i]->RxdHead+length+4]==CheckSum(Port, ComLink[i]->RxdBuf+ComLink[i]->RxdHead))//校验正确
&&(ComLink[i]->RxdBuf[ComLink[i]->RxdHead+length+4+1]==ENDCODE))//结束码正确
{
if (ComLink[i]->RxdHead>0)
{
memcpy(ComLink[i]->RxdBuf,ComLink[i]->RxdBuf+ComLink[i]->RxdHead,ComLink[i]->RxdTail-ComLink[i]->RxdHead);//报文与缓冲区对齐
ComLink[i]->RxdTail-=ComLink[i]->RxdHead;
ComLink[i]->RxdHead=0;
}
ComLink[i]->RxdHead+=(ComLink[i]->RxdBuf[1]+6);//头指针后移到报文后
ComLink[i]->RxdStatus=RXDSTART;
//Stop=TRUE;
S101_2002ExeDLFunCode68(Port);
if (ComLink[i]->RxdTail>ComLink[i]->RxdHead)
OSFlagPost(ComDb[i]->Event, NEXTFRAME, OS_FLAG_SET, &err);
}
else
{
ComLink[i]->RxdHead+=6;
ComLink[i]->RxdStatus=RXDSTART;
}
}
else//报文未收全,不处理,继续等待数据。
Stop=TRUE;
break;
case STARTCODE10:
if (ComLink[i]->RxdHead>0)
{
memcpy(ComLink[i]->RxdBuf,ComLink[i]->RxdBuf+ComLink[i]->RxdHead,ComLink[i]->RxdTail-ComLink[i]->RxdHead);
ComLink[i]->RxdTail-=ComLink[i]->RxdHead;
ComLink[i]->RxdHead=0;
}
ComLink[i]->RxdHead+=4+ComLink[i]->LinkAddrSize;
ComLink[i]->RxdStatus=RXDSTART;
//Stop=TRUE;
S101_2002ExeDLFunCode10(Port);
if (ComLink[i]->RxdTail>ComLink[i]->RxdHead)
OSFlagPost(ComDb[i]->Event, NEXTFRAME, OS_FLAG_SET, &err);
break;
}
}
}
}
//检测10帧正确性
BOOL S101_2002ExeDLFun10(INT8U Port)
{
INT8U i;
INT8U *p;
INT16U addr=0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -