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

📄 iec103_xuji.cpp

📁 许继公司103规约源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	else
		DafaultPtlPara();

	m_pCH->m_ChConfig.byPtlKind=0;

	m_ePtlType = ptl103;
	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);			
	
	// 总召唤间隔
	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_XUJIPtl::OnTimer(void)
{
	m_nCnt++;
}

//组帧函数
INT CIEC103_XUJIPtl::Frame(BYTE* pSendBuf, INT nLen)
{
	INT nret = 0;
	// 总召唤/召唤脉冲计数定时到
	if (m_IEC103Data.m_queryCnt.IsOverTime(m_nCnt))
	{
		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();				// 循环查询任务
		}

		// 转入链路帧发送过程
		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_XUJIPtl::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_XUJIPtl::PackLPDU_Fix(BYTE byNodeID, BYTE byCode)
{
//	if(m_IEC103Data.m_frmOver.IsOverTime(m_nCnt))
	{
		PackLPDU(byNodeID, byCode);
	}
}

void CIEC103_XUJIPtl::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_XUJIPtl::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
				{
					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)
						Pack_Asdu_88(m_IEC103Data.m_byCycCnt);
				}else// 总召唤
					Pack_Asdu_7(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_XUJIPtl::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_XUJIPtl::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);
}

//任务组帧
BOOL CIEC103_XUJIPtl::PackTask(void)
{
	TASK *pTask = NULL;
	pTask = m_pCH->GetTask();
	// 检索通道命令
	if (!pTask)
		return FALSE;	

	// 时间校准命令
	if (taskAdjustTime == pTask->eTaskType)
	{	
		return FALSE;
/*		m_bAdjustTime = true;
		return SendAdjustTime103(pTask);
*/	}

	RealRunIED *pDevRun = m_IEC103Data.m_RunIed[pTask->byDestNodeID];
	if(!pDevRun)
		return FALSE;
	if (tsNull == pTask->eStatus)
		return FALSE;
	
	//判断是否任务队列已经冻结,如果没有冻结认为是新任务,则清数据区
	// 任务检测:数据区、设备描述区、系统描述区
//	if(!m_pCH->m_pTaskQue->IsLock())
	{
		memset(&m_IEC103Data.m_task103, 0, sizeof(m_IEC103Data.m_task103));
		// 记录规约运行号
		m_IEC103Data.m_task103.wStep = 0;
		m_IEC103Data.m_task103.task = *pTask;
	}

	BOOL bRtn = FALSE;
	//在下列任务类型中选择需要冻结得任务类型,然后调用冻结函数冻结任务队列
	//在解帧函数中,调用解除任务队列冻结函数
	if (!PackLinkCmm(pTask->byDestNodeID))
	{
		switch(pTask->eTaskType)
		{		
			// 任务类型
			case taskCmdYkSelect: 			// 遥控选择
			case taskCmdYkExecute: 			// 遥控执行
			case taskCmdYkCancel: 			// 遥控取消
				{	
					bRtn = PackYaoKong(pTask, pDevRun);
				//	if(bRtn)
				//		m_pCH->m_pTaskQue->LockTask();
				}
				break;
			case taskAskBhYc:				//保护相关:模拟量、定值、复归
				{// 召唤保护模拟量
					bRtn = PackCallProtMea(pTask, pDevRun);
				//	if(bRtn)
				//		m_pCH->m_pTaskQue->LockTask();
				}
				break;
			case taskAskBhdz:		
				{// 召唤保护定值
					bRtn = PackCallProtSetting(pTask, pDevRun);
				//	if(bRtn)
				//		m_pCH->m_pTaskQue->LockTask();
				}
				break;
			case taskCmdModifyBhdz:		
				{// 修改保护定值
					bRtn = PackModifyProtSetting(pTask, pDevRun);
				//	if(bRtn)
				//		m_pCH->m_pTaskQue->LockTask();
				}
				break;
			case taskCmdEnableBhdz:			
				{// 确认保护定值
					bRtn = PackEnableProtSetting(pTask, pDevRun);
				//	if(bRtn)
				//		m_pCH->m_pTaskQue->LockTask();
				}
				break;
			case taskCmdCancelBhdz:			
				{// 取消修改保护定值
					bRtn = PackCancelProtSetting(pTask, pDevRun);
				//	if(bRtn)
				//		m_pCH->m_pTaskQue->LockTask();
				}
				break;
			case taskCmdSetBhdzGroup:	
				{// 设置保护定值组
					bRtn = PackModifyProtSettingGroup(pTask, pDevRun);
				//	if(bRtn)
				//		m_pCH->m_pTaskQue->LockTask();
				}
				break;
			case taskCmdEnableBhdzGroup:
				{// 确认设置的保护定值组
					bRtn = PackEnableProtSettingGroup(pTask, pDevRun);
				//	if(bRtn)
				//		m_pCH->m_pTaskQue->LockTask();
				}
				break;
			case taskCmdCancelBhDzGroup:	
				{// 取消修改定值组号
					bRtn = PackCancelProtSettingGroup(pTask, pDevRun);
				//	if(bRtn)
				//		m_pCH->m_pTaskQue->LockTask();
				}
				break;
			case taskCmdBhReset:			// 保护复归
				bRtn = PackProtRes(pTask, pDevRun);

⌨️ 快捷键说明

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