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

📄 mgt100.c

📁 南瑞动控继电保护装置MGT100系列串口103规约上位机通讯程序 基于LINUX
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************************************/
#include "includes.h"
#include "mgt100.h"

void 	mgt100(unsigned char);									  	//IEC 103 PROTOCOL
void  mgt100Creat_Data(unsigned char);			    	//创建上传量参数表
void	FixFrameData(unsigned char,unsigned char);	//发送固定帧,实现复位通讯单元、复位帧计数位、请求链路状态、召唤一、二级数据
void  SendASDU6(unsigned char,unsigned char);   	//ASDU6校时
void  SendASDU7(unsigned char,unsigned char);   	//ADSU7总召唤
void  SendASDU20(unsigned char,unsigned char);   	//ADSU20 LED复位 
void  SendASDU64(unsigned char,unsigned char,unsigned char,unsigned char);   	//ADSU64 发送遥控命令 
int 	ReadComData(unsigned char );              	//对端口读到的报文进行通讯差错处理,如无差错则显示报文
void  ReceiveFixFrame_Data_Analys(unsigned char); //分析接受数据-短帧
void  ReceiveASDU_Data_Analys(unsigned char,unsigned char);     //分析接受数据-长帧
void	ReceiveASDU1(struct Master_Data*,unsigned char*);  	//解析SOE,含动作值
void	ReceiveASDU15(struct Master_Data*,unsigned char*);  //解析遥测
void	ReceiveASDU41(struct Master_Data*,unsigned char*);	//解析单点信息开关变位(突变主动上传)
void  ExeOperate(unsigned char);                          //检查端口是否有遥控命令
int   MEA(unsigned char Data0,unsigned char Data1);       //求带品质描述的遥测值

unsigned long	m_dwClockTm[port_num];

/***************************mgt100通信规约:IEC 103 PROTOCOL*************************************/
void 	mgt100(unsigned char Port)
{	
	unsigned char	i;
	unsigned 	long	m_dwClockDz;    
  
	if(!DevPort[Port]->Protocol_Start)						//上电初次执行规约程序		
		{
			DevPort[Port]->Protocol_Start = 1;
			mgt100Creat_Data(Port);									//创建上传数据	
			for(i=0;i<DevPort[Port]->Adr_Num;i++)
    	{
				DevPort[Port]->Rtu_Adr = DevPort[Port]->Adr_Id[i];
				
				m_FCV_Status[DevPort[Port]->Rtu_Adr]=0x00;
				m_Control[DevPort[Port]->Rtu_Adr]=0x50;
				m_nSCN[DevPort[Port]->Rtu_Adr]=0;
				
				FixFrameData(Port,C_RFB_NA_3);	//复位帧计数位
				FixFrameData(Port,C_RCU_NA_3);	//复位通信单元    		
				FixFrameData(Port,C_RLK_NA_3);	//请求链路状态	
				FixFrameData(Port,C_PL1_NA_3);  //0x0a 召唤一级用户数据	
				SendASDU6(Port,TYP_C_SYN_TA_3);	//ASDU6校时
				SendASDU7(Port,TYP_C_IGI_NA_3); //ADSU7总召唤 	 
			}
			m_dwClockTm[Port] = g_dwClock100ms;
		}	
	else		
	{
		
		//每隔5分钟复位通讯单元、复位帧计数位、校时以及总召唤     
    if(m_dwClockTm[Port]+9000 <= g_dwClock100ms)
    {
    	 m_dwClockTm[Port] = g_dwClock100ms;
    	 
    	 SendASDU6(Port,TYP_C_SYN_TA_3);//ASDU6校时
    	 
    	 for(i=0;i<DevPort[Port]->Adr_Num;i++)
    	 {
    	 		DevPort[Port]->Rtu_Adr = DevPort[Port]->Adr_Id[i];   
    	 		FixFrameData(Port,C_RFB_NA_3); // 复位帧计数位 	 		     	 	
    	 		FixFrameData(Port,C_RCU_NA_3); // 复位通信单元    			
    	 		FixFrameData(Port,C_RLK_NA_3); // 请求链路状态   	    	 		 	
    	 		SendASDU7(Port,TYP_C_IGI_NA_3);// ADSU7总召唤   
    		}	  
    }	
    
		for(i=0;i<DevPort[Port]->Adr_Num;i++)
		{
      DevPort[Port]->Rtu_Adr = DevPort[Port]->Adr_Id[i];			
			ExeOperate(Port);  
			FixFrameData(Port,C_PL2_NA_3);    //0x0b 召唤二级用户数据		
		}
	
	}	
	return;
}

//读取端口数据
int ReadComData(unsigned char Port)//对端口读到的报文进行通讯差错处理,如无差错则显示报文
{
	unsigned char *pRx = DevPort[Port]->rxbuf;
  unsigned char AddSum_Code;
  unsigned char Length; 
  unsigned char i; 

	usleep(50000);

  if(ReadPort(Port,pRx,7) < 7)//先读前7个字节判断
  {
  	ClearCom(Port);
  	return (FALSE);
	}

  if(pRx[2]==0x10)//短帧
  {
    if(pRx[6]!=0x16)//帧尾出错
  	{
  		ClearCom(Port);
  		return (FALSE);
		}         
    if(pRx[5]!=AddSum(DevPort[Port]->rxbuf+2,2,1))//校验错
    {
  		ClearCom(Port);
  		return (FALSE);
		}    
    for(i=0;i<7;i++)//打印出读到的短帧
		{
			printf("%x ",pRx[i]); 
		}
		printf("\n");
    if(DevPort[Port]->display_read_msg)
  	{
  		DevPort[Port]->RTU_READ_BYTE = 7; 	//长帧为固定帧长
			DevPort[Port]->display_read_msg = 0;//置显示接收报文标志		
			memcpy(DevPort[Port]->dis_rxbuf,DevPort[Port]->rxbuf,DevPort[Port]->RTU_READ_BYTE);//拷贝报文,用于显示 
  	}
  }
    
 	if((pRx[2]==0x68)&&(pRx[5]==0x68))//长帧
  {
    if(pRx[3]!=pRx[4])
  	{
  		ClearCom(Port);
  		return (FALSE);
		}
    Length = pRx[3];    //数据长度   
    if(ReadPort(Port,pRx+7,Length+1) < Length+1)
    {
  		ClearCom(Port);
  		return (FALSE);
		}       		//数据没读完出错
    
    if(pRx[Length+7]!=0x16) //帧尾出错
    {
  		ClearCom(Port);
  		return (FALSE);
		} 
		 
    AddSum_Code = AddSum(DevPort[Port]->rxbuf+2,Length,0);
    
    if(AddSum_Code!=pRx[Length+6]) //校验出错
    {
  		ClearCom(Port);
  		return (FALSE);
		}
		for(i=0;i<Length+8;i++)//打印出读到的短帧
		{
			printf("%x ",pRx[i]); 
		} 
		printf("\n");
    if(DevPort[Port]->display_read_msg)
  	{
  		DevPort[Port]->RTU_READ_BYTE = Length+8; //长帧为可变帧长
			DevPort[Port]->display_read_msg = 0;//置显示接收报文标志		
			memcpy(DevPort[Port]->dis_rxbuf,DevPort[Port]->rxbuf,DevPort[Port]->RTU_READ_BYTE);//拷贝报文,用于显示 
  	}         
  }     

	usleep(100000);	
  return(TRUE);
}

void  ReceiveFixFrame_Data_Analys(unsigned char Port)  //分析接受数据-短帧
{ 
	unsigned char  *pRx=DevPort[Port]->rxbuf;
	unsigned char	 m_Control;
	
	m_Control=pRx[1]&0x0f;
	
	switch(m_Control)
	{
		case M_CON_NA_3://0:确认
			break;
		case M_BY_NA_3://1:确认 链路忙
			break;
		case M_DATA_NA_3://8=以数据响应请求
			break;
		case M_NV_NA_3://9=无所召唤的数据
			break;
		case M_LKR_OK_NA_3://11=链路状态
			break;
		case M_LKR_NW_NA_3://14=链路服务未工作
			break;
		case M_LKR_NR_NA_3://15=链路服务未完成
			break;
		default:
			m_Control=0xff;
		break;
	}
}

void  ReceiveASDU_Data_Analys(unsigned char Port,unsigned char	ycflag)    //分析接受数据-长帧
{
	unsigned char *pRx = DevPort[Port]->rxbuf;
	unsigned char adr_offset;
	unsigned char Func_Code;
	unsigned char	m_TYP;
	unsigned char m_COT;
	unsigned char m_FUN;
	unsigned char m_INF;	
	
	if(!ReadComData(Port))   //判断读取数据成功
	{
		pRx=pRx+2;//过滤开头的两字节“00 00”
		if((pRx[0]==0x68)&&(pRx[3]==0x68))	//处理ASDU长帧报文
		{
			m_FCV_Status[DevPort[Port]->Rtu_Adr]=pRx[4] & 0x20;
						
			adr_offset = Serch_Adr(*(pRx+5)); //查找该地址号在地址表中的位置 
  		if(adr_offset==0xff)
   			return;

  		DataAdr[adr_offset]->Addr = *(pRx+5);		//保存地址号
    
			m_TYP=pRx[6];	//类型标志
			m_COT=pRx[8];	//传送原因
			m_FUN=pRx[10];//功能类型
			m_INF=pRx[11];//信息序号

			switch(m_TYP)
			{
				case 1://SOE事件
					ReceiveASDU1(DataAdr[adr_offset],pRx);
					break;
				case 15://遥测(包括16个遥信量)
					ReceiveASDU15(DataAdr[adr_offset],pRx);
					break;
				case 41://单点信息状态变位-遥信变位(突变)
					ReceiveASDU41(DataAdr[adr_offset],pRx);
					break;
				default:
					m_TYP=0xff;
					break;
			}
		}

		if(pRx[0]==0x10)
		{
			m_FCV_Status[DevPort[Port]->Rtu_Adr]=pRx[1] & 0x20;
			
			if((pRx[1]&0x0f==0x09)||(pRx[1]&0x0f==0x0b))
			{				
				return;	
			}			
		}
		
		if(m_FCV_Status[DevPort[Port]->Rtu_Adr])
		{				
			FixFrameData(Port,C_PL1_NA_3); //0x0a 召唤一级用户数据
			m_FCV_Status[DevPort[Port]->Rtu_Adr]=0x00;
			return;
		}	
	}
	ClearRx(Port);
	return;
}

void FixFrameData(unsigned char Port,unsigned char ControlByte)//发送固定帧,实现复位通讯单元、复位帧计数位、请求链路状态、召唤一、二级数据
{
	unsigned char *pTx = DevPort[Port]->txbuf;
	switch(ControlByte)
	{
		case C_RCU_NA_3://复位通信单元
		{
			*pTx++ = 0x10;
			*pTx++ = 0x40;
			*pTx++ = DevPort[Port]->Rtu_Adr;
			*pTx++ = AddSum(DevPort[Port]->txbuf,2,1);
			*pTx++ = 0x16;
			ClearCom(Port);	
			WriteCom(Port,pTx-DevPort[Port]->txbuf);
			ReceiveASDU_Data_Analys(Port,0);
			
			break;
		}
		case C_RFB_NA_3://复位帧计数位
		{	
			*pTx++ = 0x10;
			*pTx++ = 0x47;
			*pTx++ = DevPort[Port]->Rtu_Adr;
			*pTx++ = AddSum(DevPort[Port]->txbuf,2,1);
			*pTx++ = 0x16;
			ClearCom(Port);	
			WriteCom(Port,pTx-DevPort[Port]->txbuf);
			ReceiveASDU_Data_Analys(Port,0);
			
			break;
		}
		case C_RLK_NA_3://请求链路状态
		{
			*pTx++ = 0x10;
			*pTx++ = 0x49;
			*pTx++ = DevPort[Port]->Rtu_Adr;
			*pTx++ = AddSum(DevPort[Port]->txbuf,2,1);
			*pTx++ = 0x16;
			ClearCom(Port);	
			WriteCom(Port,pTx-DevPort[Port]->txbuf);			
			ReceiveASDU_Data_Analys(Port,0);
			
			break;
		}
		case C_PL1_NA_3://召唤一级用户数据
		{
			unsigned char m_FCB_status;
			*pTx++ = 0x10;
			*pTx++ = m_Control[DevPort[Port]->Rtu_Adr]|0x0a;
			m_Control[DevPort[Port]->Rtu_Adr]=m_Control[DevPort[Port]->Rtu_Adr]^0x20;
			*pTx++ = DevPort[Port]->Rtu_Adr;
			*pTx++ = AddSum(DevPort[Port]->txbuf,2,1);
			*pTx++ = 0x16;
			ClearCom(Port);	
			WriteCom(Port,pTx-DevPort[Port]->txbuf);			
			ReceiveASDU_Data_Analys(Port,0);

			break;
		}
		case C_PL2_NA_3://召唤二级用户数据
		{
			*pTx++ = 0x10;
			*pTx++ = m_Control[DevPort[Port]->Rtu_Adr]|0x0b;
			m_Control[DevPort[Port]->Rtu_Adr]=m_Control[DevPort[Port]->Rtu_Adr]^0x20;
			*pTx++ = DevPort[Port]->Rtu_Adr;
			*pTx++ = AddSum(DevPort[Port]->txbuf,2,1);
			*pTx++ = 0x16;
			ClearCom(Port);	
			WriteCom(Port,pTx-DevPort[Port]->txbuf);
			ReceiveASDU_Data_Analys(Port,1);
						
			break;	
		}
		default: return;					
	}	
}

void SendASDU6(unsigned char Port,unsigned char ASDU_TYP)//校时,广播地址addr=0xff
{
	unsigned char *pTx = DevPort[Port]->txbuf;
	unsigned char SendASDU_Length;
	int i;
	*pTx++ = 0x68;
	*pTx++ = 0x0f;
	*pTx++ = 0x0f;
	*pTx++ = 0x68;
	*pTx++ = 0x43;
	*pTx++ = 0xff;
	*pTx++ = 0x06;
	*pTx++ = 0x81;
	*pTx++ = 0x08;
	*pTx++ = 0xff;
	*pTx++ = 0xff;
	*pTx++ = 0x00;
	int temp= t_data.sec*1000;
	
	*pTx++ = (unsigned char)(temp%256);	//毫秒L
  *pTx++ = (unsigned char)(temp/256);	//毫秒H  
  *pTx++ = t_data.min;								//分
  *pTx++ = t_data.hour;								//时
  *pTx++ = t_data.day;								//日
  *pTx++ = t_data.mon;								//月
  *pTx++ = t_data.year-2000;					//年 
  *pTx++ = AddSum(DevPort[Port]->txbuf,15,0);
  *pTx++ = 0x16;
	ClearCom(Port);	
	WriteCom(Port,pTx-DevPort[Port]->txbuf);
	ReceiveASDU_Data_Analys(Port,0);
		
}

⌨️ 快捷键说明

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