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

📄 iec103_sf.cpp

📁 四方公司103规约
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	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 + -