📄 iec103_sf.cpp
字号:
void CIEC103_SFPtl::DafaultPtlPara(void)
{
// 保护遥信复归
m_IEC103PtlPara.bOrdAfmReset = 0; // 确认复归(复归命令肯定确认时,保护信号复归)
m_IEC103PtlPara.bOrderReset = 0; // 命令复归(复归命令毋须确认,保护信号即可复归)
// 信息存储
m_IEC103PtlPara.bEventVirtualYX = 0; // 故障事项虚遥信
// 通用参数
m_IEC103PtlPara.byInitNum = 1; // 初始化重传次数
m_IEC103PtlPara.dwFrameOver = 2000; // 帧超时间隔,ms
m_IEC103PtlPara.dwQuery = 180; // 总查询间隔,s
m_IEC103PtlPara.wTimeOver = 600; // 校时间隔,s
m_IEC103PtlPara.bCommAddr = 1; // 默认为1,才有cpu地址,否则为单元地址(即链路层地址)
m_IEC103PtlPara.byBHCPUAddr = 1; // 保护cpu地址,默认为1
m_IEC103PtlPara.byCKCPUAddr = 2; // 测控cpu地址,默认为2
m_IEC103PtlPara.bGenSel = 1;
//m_IEC103PtlPara.byBhResetFun = 0;
//m_IEC103PtlPara.byBhResetInf = 0;
}
//通道任务监视函数
BOOL CIEC103_SFPtl::WatchTask(TASK* &ptask, eTaskTyp tasktyp, BYTE byNodeID)
{
ptask = m_pCH->GetWaitingTask(tasktyp, byNodeID);
if (ptask)
return TRUE;
return FALSE;
}
//规约初始化
void CIEC103_SFPtl::InitPtl(void)
{
int i;
FlashPara103 * pflashpara = NULL;
pflashpara = (FlashPara103*)(m_pCH->m_PtlPara);
if(pflashpara)
FlashParaToPtlPara(pflashpara);
else
DafaultPtlPara();
m_pCH->m_ChConfig.byPtlKind=0;
m_ePtlType = ptlSIFANG103;
for(i=0; i<m_pCH->m_ChConfig.byIEDNum; i++)
{
CIED *pIED = m_pCH->m_pIED[i];
if(pIED == NULL)
continue;
CreateRealRunIED(pIED);
m_IEC103Data.m_addrtoID[pIED->m_IEDConfig.byNodeAddr] = pIED->m_IEDConfig.byNodeID;
}
// 规约运行步骤
m_IEC103Data.m_runStep = PtlRun_PackASDU;
m_IEC103Data.m_byCycCnt = 0;
// 规约任务区
memset(&m_IEC103Data.m_task103, 0, sizeof(m_IEC103Data.m_task103));
// 服务原语
memset(&m_IEC103Data.m_prmSend, 0, sizeof(CommPrim));
memset(&m_IEC103Data.m_prmRecv, 0, sizeof(CommPrim));
// 收发缓冲区
m_IEC103Data.m_wLinkLen = 0;
m_IEC103Data.m_wSendNum = 0;
// 计时器初始化
DWORD dwRatio = GetChRatio();
DWORD dwDly = (3*11*1000 + dwRatio-1) / dwRatio;
// 帧超时时间
m_IEC103Data.m_frmOver.SetWaitSpan(m_IEC103PtlPara.dwFrameOver);
// 帧间隔时间
m_IEC103Data.m_frmDly33.SetWaitSpan(dwDly*300);
// 总召唤间隔
m_IEC103Data.m_queryCnt.SetWaitSpan((m_IEC103PtlPara.dwQuery/2) * 1000);
m_IEC103Data.m_queryCnt.Start(m_nCnt);
//校时间隔
m_IEC103Data.m_timeover.SetWaitSpan(m_IEC103PtlPara.wTimeOver * 1000);
m_IEC103Data.m_timeover.Start(m_nCnt);
// 通道无数据接收监视,
m_IEC103Data.m_lnkSerialError = 0;
m_IEC103Data.m_bySendCnt = 0;
m_IEC103Data.m_bySin = 0;
memset(&m_IEC103Data.m_OldCmd, 0, sizeof(m_IEC103Data.m_OldCmd));
QueryRecvLPDU();
m_nCnt = 0;
SetTimer(2);
m_bAdjustTime = false;
}
void CIEC103_SFPtl::OnTimer(void)
{
m_nCnt++;
}
//组帧函数
INT CIEC103_SFPtl::Frame(BYTE* pSendBuf, INT nLen)
{
INT nret = 0;
// 总召唤/召唤脉冲计数定时到
if (m_IEC103Data.m_queryCnt.IsOverTime(m_nCnt))//调试1000
{
m_IEC103Data.m_queryCnt.Start(m_nCnt);
for (int i = 0; i < CH_MAX_IED_NUM; i++)
{
RealRunIED *pRunIED = m_IEC103Data.m_RunIed[i];
if(pRunIED)
{
pRunIED->queryFull ^= 1; // 查询标志取反
pRunIED->query = 1;
}
}
}
/*应用层组帧
* 1) 发送通道任务命令
* 2) 发送普通的循环任务
*/
if (PtlRun_PackASDU == m_IEC103Data.m_runStep)
{
// 要求进行组帧处理
m_IEC103Data.m_wSendNum = 0;
m_IEC103Data.m_wLinkLen = 0;
// 初始化服务原语
memset(&m_IEC103Data.m_prmSend, 0, sizeof(CommPrim));
memset(&m_IEC103Data.m_prmRecv, 0, sizeof(CommPrim));
// 通道任务检测
if (!PackTask()) //无任务时,则执行PackCyc();若有任务,则先执行任务
{
PackCyc(); // 循环查询任务
}
// 转入链路帧发送过程
m_IEC103Data.m_bySendCnt = 0;
if (m_IEC103Data.m_wSendNum > 0)
m_IEC103Data.m_runStep = PtlRun_SendLPDU;
}
// 辅机直接转入链路接收过程中
/*if (!lpCh->m_pDevDB->GetCcsModule( ))
{
pPtlData->m_runStep = PtlRun_RecvLPDU;
QueryRecvLPDU(lpCh);
}*/
// 等待链路接收
if (PtlRun_RecvLPDU == m_IEC103Data.m_runStep)
{
if (m_IEC103Data.m_frmOver.IsOverTime(m_nCnt))
{
m_IEC103Data.m_bySendCnt ++;
if (m_IEC103Data.m_bySendCnt > 2)
{
NoLPDU();
m_IEC103Data.m_runStep = PtlRun_PackASDU;
}
else
m_IEC103Data.m_runStep = PtlRun_SendLPDU;
}
}
// 链路层发送
if (PtlRun_SendLPDU == m_IEC103Data.m_runStep)
{
// 主机发送数据,辅机仅接收数据
//if (lpCh->m_pDevDB->GetCcsModule( ))
//{
// 等待超时监视
if(m_bAdjustTime)
{
m_bAdjustTime = false;
m_IEC103Data.m_runStep = PtlRun_PackASDU;
nret = m_IEC103Data.m_wSendNum;
}
else
nret = PtlSendLPDU();
memcpy(pSendBuf, m_IEC103Data.m_bySend, nret);
//}
}
return nret;
}
// 链路层传输服务
// 1. 站初始化
// 2. 链路状态控制
BOOL CIEC103_SFPtl::PackLinkCmm(BYTE byNodeID)
{
RealRunIED *pDevRun = m_IEC103Data.m_RunIed[byNodeID];
if(!pDevRun)
return FALSE;
if (!pDevRun->linkQuery && !pDevRun->linkRes)
return FALSE;
if (pDevRun->linkRes)
{
PackLPDU_Fix(byNodeID, ResCU_code);
pDevRun->bCommInitFlag = TRUE;
pDevRun->nASDU5Cnt = 0;
pDevRun->step = eInitStart;
}
else if (pDevRun->linkQuery)
{ // 链路状态
PackLPDU_Fix(byNodeID, QueryLink_code);
}
return TRUE;
}
// 固定帧长链路数据组帧
void CIEC103_SFPtl::PackLPDU_Fix(BYTE byNodeID, BYTE byCode)
{
// if(m_IEC103Data.m_frmOver.IsOverTime(m_nCnt))
{
PackLPDU(byNodeID, byCode);
}
}
void CIEC103_SFPtl::PackLPDU(BYTE byNodeID, BYTE code)
{
RealRunIED *pDevRun = m_IEC103Data.m_RunIed[byNodeID];
if(!pDevRun)
return;
LinkCtrl linkCtrl;
linkCtrl.funcode = code;
linkCtrl.res = 0;
linkCtrl.prm = 1;
switch(code)
{
case ResCU_code:
case ResFcb_code:
m_IEC103Data.m_lnkSvrCls = SendConfirm;
linkCtrl.fcvDfc = 0;
break;
case NoReply_code:
m_IEC103Data.m_lnkSvrCls = SendNoreply;
linkCtrl.fcvDfc = 0;
break;
case QueryLink_code:
m_IEC103Data.m_lnkSvrCls = RequestRespond;
linkCtrl.fcvDfc = 0;
break;
case SendCon_code:
m_IEC103Data.m_lnkSvrCls = SendConfirm;
linkCtrl.fcvDfc = 1;
break;
case CallClass1_code:
case CallClass2_code:
m_IEC103Data.m_lnkSvrCls = RequestRespond;
linkCtrl.fcvDfc = 1;
break;
default:
break;
}
// 链路帧控制字
linkCtrl.fcbAcd = 0;
if (linkCtrl.fcvDfc)
{
pDevRun->fcb = ~pDevRun->fcb;
linkCtrl.fcbAcd = pDevRun->fcb;
}
if (0 == m_IEC103Data.m_wSendNum)
{ // 固定帧长
LPDU_Fix_Fmt *pFmt = (LPDU_Fix_Fmt *)(m_IEC103Data.m_bySend);
pFmt->head = 0x10;
pFmt->ctrl = linkCtrl;
pFmt->addr = pDevRun->pDevData->m_IEDConfig.byNodeAddr;
pFmt->sum = pFmt->ctrl.lnkCtrl + pFmt->addr;
pFmt->tail = 0x16;
m_IEC103Data.m_wSendNum = sizeof(LPDU_Fix_Fmt);
}
else
{
LPDU_Vol_Head *pHead = (LPDU_Vol_Head *)(m_IEC103Data.m_bySend);
pHead->head1 = pHead->head2 = 0x68;
pHead->len1 = pHead->len2 = m_IEC103Data.m_wSendNum + 2;
pHead->ctrl = linkCtrl;
pHead->addr = pDevRun->pDevData->m_IEDConfig.byNodeAddr;
m_IEC103Data.m_wSendNum += sizeof(LPDU_Vol_Head);
m_IEC103Data.m_bySend[m_IEC103Data.m_wSendNum ++] = SumMod(m_IEC103Data.m_bySend + 4, pHead->len1);
m_IEC103Data.m_bySend[m_IEC103Data.m_wSendNum ++] = 0x16;
}
}
//循环查询组帧
/****
*PackCyc - 循环查询组帧函数
*
*功能:
* 1。总查询命令
* 2。故障录波
* 3。通用分类服务总查询
* 4。通用2级数据查询
*
****/
void CIEC103_SFPtl::PackCyc(void)
{
RealRunIED *pDevRun = m_IEC103Data.m_RunIed[m_IEC103Data.m_byCycCnt];
if (pDevRun)
{
if (!PackLinkCmm(m_IEC103Data.m_byCycCnt))
{ // 链路层组帧
/*
* 应用层组帧
*
*命令优先级
* 1。扰动数据传输
* 2。通用分类服务总查询
* 3。召唤电度脉冲量
* 4。总查询(总召唤)
* 5。循环查询2级数据
**/
if(pDevRun->bCommInitFlag && !pDevRun->acd)
{
if(eInitTime == pDevRun->step && pDevRun->nASDU5Cnt>=2)//校时
{
SendAdjustTime103(pDevRun->pDevData->m_IEDConfig.byNodeAddr);
}
else if(eInitGenAsk == pDevRun->step)//总召唤
{
Pack_Asdu_7(m_IEC103Data.m_byCycCnt);
}
else if(eInitGenGroupAsk == pDevRun->step)//通用分类服务总召唤 new
{
pDevRun->bGenGroupQury = TRUE; //new
Pack_ASDU_21(m_IEC103Data.m_byCycCnt);
}
else
{
BYTE Code = CallClass2_code;
PackLPDU_Fix(m_IEC103Data.m_byCycCnt, Code);
}
}
else if (!pDevRun->acd && pDevRun->query && !pDevRun->bCommInitFlag)
{
if (!pDevRun->queryFull)
{// 召唤电度量
if(pDevRun->pDevData->m_IEDConfig.nDdNum > 0)
{
if (m_IEC103PtlPara.bGenSel) //在规约参数中,若设置bGenSel为1,
{ //则采用通用分类方式召唤电度量
pDevRun->bDdQury = TRUE;
Pack_ASDU_21(m_IEC103Data.m_byCycCnt); //new
//printf("电度召唤:pDevRun->query = %d\n",pDevRun->query);
}
else
Pack_Asdu_88(m_IEC103Data.m_byCycCnt);
}
}
else// 总召唤
{
Pack_Asdu_7(m_IEC103Data.m_byCycCnt);
if (pDevRun->bQuryEnd)
{
pDevRun->bQuryEnd = FALSE;
pDevRun->bGenGroupQury = TRUE; //new
Pack_ASDU_21(m_IEC103Data.m_byCycCnt); //四方
}
}
// 清除查询标志
pDevRun->query = 0;
}
else if(m_IEC103Data.m_timeover.IsOverTime(m_nCnt) && !pDevRun->bCommInitFlag)//校时
{
m_IEC103Data.m_timeover.Start(m_nCnt);
BYTE byaddr = 0xff;
SendAdjustTime103(byaddr);
m_bAdjustTime = true;
}
else
{ // 通用查询
BYTE byCode = CallClass2_code;
if (pDevRun->acd)
byCode = CallClass1_code;
PackLPDU_Fix(m_IEC103Data.m_byCycCnt, byCode);
}
}
}
m_IEC103Data.m_byCycCnt = (m_IEC103Data.m_byCycCnt+1) % CH_MAX_IED_NUM;
}
//asdu88
void CIEC103_SFPtl::Pack_Asdu_88(BYTE byNodeID)
{
RealRunIED *pDevRun = m_IEC103Data.m_RunIed[byNodeID];
BYTE byAddr = 0;
if(m_IEC103PtlPara.bCommAddr)
byAddr = m_IEC103PtlPara.byCKCPUAddr;
else
byAddr = pDevRun->pDevData->m_IEDConfig.byNodeAddr;
ASDU_88_Fmt *pFmt = (ASDU_88_Fmt *)(m_IEC103Data.m_bySend + sizeof(LPDU_Vol_Head));
pFmt->head.type = 88;
pFmt->head.vsq.vsq = 0x81;
pFmt->head.cot = 0x02;
pFmt->head.addr = byAddr;//
pFmt->head.fun = 1;
pFmt->head.inf = 0;
pFmt->qcc.frz = 0;
pFmt->qcc.rqt = 5;
pFmt->rii = m_IEC103Data.m_bySin ++;
m_IEC103Data.m_wSendNum = sizeof(ASDU_88_Fmt);
PackLPDU(byNodeID, SendCon_code);
}
//asdu7
void CIEC103_SFPtl::Pack_Asdu_7(BYTE byNodeID)
{
RealRunIED *pDevRun = m_IEC103Data.m_RunIed[byNodeID];
BYTE byAddr = 0;
if(m_IEC103PtlPara.bCommAddr)
byAddr = m_IEC103PtlPara.byCKCPUAddr;
else
byAddr = pDevRun->pDevData->m_IEDConfig.byNodeAddr;
ASDU_7_Fmt *pFmt = (ASDU_7_Fmt *)(m_IEC103Data.m_bySend + sizeof(LPDU_Vol_Head));
pFmt->head.type = 7;
pFmt->head.vsq.vsq = 0x81;
pFmt->head.cot = 9;
pFmt->head.addr = byAddr;
pFmt->head.fun = 0xff;
pFmt->head.inf = 0;
pFmt->scn = m_IEC103Data.m_bySin ++;
m_IEC103Data.m_wSendNum = sizeof(ASDU_7_Fmt);
PackLPDU(byNodeID, SendCon_code);
}//end Pack_ASDU7()
//通用分类服务总查询 ASDU21
void CIEC103_SFPtl::Pack_ASDU_21(BYTE byNodeID)
{
RealRunIED* pRunIED = m_IEC103Data.m_RunIed[byNodeID];
BYTE addr = 0;
if (m_IEC103PtlPara.bCommAddr)//1:CPU地址
addr = m_IEC103PtlPara.byCKCPUAddr;
else
addr = pRunIED->pDevData->m_IEDConfig.byNodeAddr;
if (pRunIED->bGenGroupQury)
{
ASDU_21_Qury* pFmt = (ASDU_21_Qury*)(m_IEC103Data.m_bySend + sizeof(LPDU_Vol_Head));
pFmt->head.type = C_GC_NA_3;//0x15
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -