#include "..\public\public.h"
#include "..\bottom\bottom.h"
#include "..\protocal\iec101.h"
#include "..\scada\scada.h"
#include "..\channel\channel.h"
#include "..\cannet\mainapp.h"
struct IEC101_STRUCT *lpIEC101; //IEC101规约私用数据指针
//功能:接收错误处理
//输入:void
//输出:void
void IEC101RErrorProcess(void)
{
lpIEC101->wRecvNum = 0;
lpChanl[ChanlNo].RErrorC++; //通道接收错误字数
lpIEC101->RErrorN++; //规约接收错误字数
if(lpIEC101->RErrorN>=MaxErrorN)
{
lpChanl[ChanlNo].RFrameC=0;//通道接收字数
lpChanl[ChanlNo].RErrorC=0;//通道接收错误字数,此处未用到
lpIEC101->RErrorN=0; //规约接收错误字数
if((lpIEC101->initstatus == initend) &&(lpIEC101->FtuSccReset == FALSE))
{
fnInitSCC(ChanlNo,SCCERROR); //复位通道
lpIEC101->FtuSccReset = TRUE; //子站状态改变
}
}
}
//链路层接收函数
//功能:链路接收,把串口接收缓冲区中的数据解出一桢
// 并放入lpIEC101->PRecvFrame.byLinkBuf
// 取出链路层地址
//输入:void
//输出:void
void Iec101LinkRecv(void)
{
u8 Count,byRecv,bySum = 0;
INT i,j;
//获取可读取的字节数
Count=GetInCount(Rece[ChanlNo].wFront,Rece[ChanlNo].wRear,RECEBUFSIZE);
if((Count==0)&&(lpIEC101->initstatus == initend) &&(lpIEC101->FtuSccReset == FALSE)) //链路初始化完成后,监视主站发帧时间间隔
{
lpIEC101->DogN++;//DOG记数
if (lpIEC101->DogN>=MaxDogN)
{
lpIEC101->DogN=0;
fnInitSCC(ChanlNo,SCCERROR); //复位通道,不会频繁复位的,不用的通道没有规约,用到的通道才有规约
lpIEC101->FtuSccReset = TRUE;//长时间收到错误的帧,时间间隔缩短
}
}
else
lpIEC101->DogN=0;//DOG记数
for(j=0;j<Count;j++)
{
byRecv=ReadByte();
if (lpIEC101->wRecvNum == 0)
{
if((byRecv!=F_STARTCODE) && (byRecv!=V_STARTCODE))
continue;
lpIEC101->byHead =byRecv;
}
if (lpIEC101->byHead==F_STARTCODE)
{
lpIEC101->byRecvBuf[lpIEC101->wRecvNum] = byRecv;
//保存启动字符
lpIEC101->wRecvNum++;
//计数器加一
if(lpIEC101->wRecvNum >=(4+lpIEC101->TypeLinkAdd)) //fu 2005.9.1
{
if(lpIEC101->byRecvBuf[lpIEC101->wRecvNum-1] == STOPCODE)
{
for(i=1 ; i<=(1+lpIEC101->TypeLinkAdd);i++) // fu 2005.9.1
bySum = bySum + lpIEC101->byRecvBuf[i];
if (bySum == lpIEC101->byRecvBuf[2+lpIEC101->TypeLinkAdd])
{
lpChanl[ChanlNo].RFrameC++; //通道接收字数
lpIEC101->DogN=0; //DOG记数
lpIEC101->RErrorN=0; //规约接收错误字数
if( ((lpIEC101->byRecvBuf[1] & 0xc0) == 0x40)
&&(lpIEC101->PRecvFrame.byFull == 0)
&&(lpIEC101->PReAppLayer.byFull == 0)
/* &&(lpIEC101->PWindow == 0)*/ )//fulianqiang 2005.10.14 配合功能码3链路响应
{
for(i=0;i<(4+lpIEC101->TypeLinkAdd);i++)
lpIEC101->PRecvFrame.byLinkBuf[i] = lpIEC101->byRecvBuf[i];
//取出链路层地址 fu 2005.9.1
lpIEC101->wRecvCmmAdd.Byte.l = lpIEC101->PRecvFrame.byLinkBuf[2];
if(lpIEC101->TypeLinkAdd==2)
{
lpIEC101->wRecvCmmAdd.Byte.h = lpIEC101->PRecvFrame.byLinkBuf[3];
}
lpIEC101->PRecvFrame.byFull = 1;
lpIEC101->PRecvFrame.wFrameLen = 4+lpIEC101->TypeLinkAdd;
}
}
else
IEC101RErrorProcess();
}
//重新搜索下一帧
lpIEC101->wRecvNum = 0;
}
}
else if (lpIEC101->byHead==V_STARTCODE)
{
lpIEC101->byRecvBuf[lpIEC101->wRecvNum] = byRecv;
lpIEC101->wRecvNum++;
if(lpIEC101->wRecvNum == 4)
{
if((lpIEC101->byRecvBuf[0]==lpIEC101->byRecvBuf[3])
&& (lpIEC101->byRecvBuf[1]==lpIEC101->byRecvBuf[2]))
lpIEC101->wRecvLen = lpIEC101->byRecvBuf[1] + 6;
else
IEC101RErrorProcess();
}
if(lpIEC101->wRecvNum >= lpIEC101->wRecvLen)
{
if(lpIEC101->byRecvBuf[lpIEC101->wRecvNum-1] == STOPCODE)
{
for (i=4 ; i<=lpIEC101->wRecvLen-3;i++)
bySum = bySum + lpIEC101->byRecvBuf[i];
if (bySum == lpIEC101->byRecvBuf[lpIEC101->wRecvLen-2])
{
lpChanl[ChanlNo].RFrameC++; //通道接收字数
lpIEC101->DogN=0; //DOG记数
lpIEC101->RErrorN=0; //规约接收错误字数
if( ((lpIEC101->byRecvBuf[4] & 0xc0) == 0x40)
&&(lpIEC101->PRecvFrame.byFull == 0)
&&(lpIEC101->PReAppLayer.byFull == 0)
/*&&(lpIEC101->PWindow == 0)*/ )
{
for(i=0;i<lpIEC101->wRecvLen;i++)
lpIEC101->PRecvFrame.byLinkBuf[i] = lpIEC101->byRecvBuf[i];
//取出链路层地址 fu 2005.9.1
lpIEC101->wRecvCmmAdd.Byte.l = lpIEC101->PRecvFrame.byLinkBuf[5];
if(lpIEC101->TypeLinkAdd==2)
{
lpIEC101->wRecvCmmAdd.Byte.h = lpIEC101->PRecvFrame.byLinkBuf[6];
}
lpIEC101->PRecvFrame.byFull = 1;
lpIEC101->PRecvFrame.wFrameLen = lpIEC101->wRecvLen;
//lpIEC101->PWindow = 1;
}
}
else
IEC101RErrorProcess();
}
//重新搜索下一帧
lpIEC101->wRecvNum = 0;
}
}
}
}
//从动链路层接收处理函数
//功能:根据链路控制字执行相应的操作:
// 1)根据功能码执行动作
// 2)FCB位判断和设置
//输入:链路控制字
//输出:void
void PLinkRecvProcessF(u8 byConField)
{
lpIEC101->PRecvFrame.byFunCode = byConField & 0x0F;
//判断是否需要切换为维护规约
if (lpIEC101->PRecvFrame.byFunCode==IEC101_SWITCH_PROTOCOL)
fnSwitchProtocol(ChanlNo); //将当前运行规约切换为维护规约
if (lpIEC101->initstatus == notinit)
{
if ( (lpIEC101->PRecvFrame.byFunCode == CALL_LINK)
||(lpIEC101->PRecvFrame.byFunCode == RESET_LINK) )
{
if (lpIEC101->PRecvFrame.byFunCode == CALL_LINK)
{
lpIEC101->PSeAppLayer.LinkFunCode = 0x0B;
if (lpIEC101->haveset == TRUE)
{
lpIEC101->initstatus = justinit;
}
}
else if (lpIEC101->PRecvFrame.byFunCode == RESET_LINK)
{
lpIEC101->PfcbC = 0;
lpIEC101->PSeAppLayer.LinkFunCode = 0x00;
lpIEC101->haveset = TRUE;
}
//
lpIEC101->PSeAppLayer.byMsgNum = 0;
lpIEC101->PSeAppLayer.byFull = 1;
}
return;
}
if ( ((byConField & 0x20)==(lpIEC101->PfcbC<<5)) && (byConField & 0x10))
{
lpIEC101->PSendFrame.byFull = 1;
return;
}
if ( (lpIEC101->PRecvFrame.byFunCode == CALL_LINK)
||(lpIEC101->PRecvFrame.byFunCode == RESET_LINK)
||(lpIEC101->PRecvFrame.byFunCode == CALL_ACD) )
{
if (lpIEC101->PRecvFrame.byFunCode == RESET_LINK)
{
lpIEC101->PfcbC = 0;
lpIEC101->PSeAppLayer.LinkFunCode = 0x00;
}
if (lpIEC101->PRecvFrame.byFunCode == CALL_LINK)
lpIEC101->PSeAppLayer.LinkFunCode = 0x0B;
if (lpIEC101->PRecvFrame.byFunCode == CALL_ACD)
lpIEC101->PSeAppLayer.LinkFunCode = 0x0B;
//
lpIEC101->PSeAppLayer.byMsgNum = 0;
lpIEC101->PSeAppLayer.byFull = 1;
}
if ((lpIEC101->PRecvFrame.byFunCode == CALL_DATA1)||(lpIEC101->PRecvFrame.byFunCode == CALL_DATA2))
{
lpIEC101->PReFrameType = lpIEC101->PRecvFrame.byFunCode;
lpIEC101->PfcbC = byConField & 0x20 ? 1 : 0; // FCV位有效,则保存FCB位
}
}
//从动应用层接收处理函数
//功能:根据链路控制字及类型标识作相应的处理
//输入:void
//输出:void
void PLinkRecvProcessV(u8 byConField)
{
u8 byFrameCount,i; // frame count fulianqiang 2005.9.1
if ( ((byConField & 0x20)==(lpIEC101->PfcbC<<5)) && (byConField & 0x10))
{
lpIEC101->PSendFrame.byFull = 1;
return;
}
lpIEC101->PReAppLayer.lpByBuf = lpIEC101->PRecvFrame.byLinkBuf;
lpIEC101->PRecvFrame.byFunCode = byConField & 0x0F;
if(3==lpIEC101->PRecvFrame.byFunCode)
{
if(3==lpIEC101->UnsolTimeInterval) //先发链路确认再等待召唤二级数据
{
lpIEC101->PReFrameType = 3;
lpIEC101->PSeAppLayer.LinkFunCode = 0x00;
lpIEC101->PSeAppLayer.byMsgNum = 0;
lpIEC101->PSeAppLayer.byFull = 1;
}
}
lpIEC101->PfcbC = byConField & 0x20 ? 1 : 0; // FCV位有效,则保存FCB位
byFrameCount=5+lpIEC101->TypeLinkAdd; //指向类型标识
lpIEC101->PReMsgType = lpIEC101->PReAppLayer.lpByBuf[byFrameCount++]; // 类型标识
lpIEC101->byQualify = lpIEC101->PReAppLayer.
评论0