📄 mgt100.c
字号:
/****************************************************************************************************/
#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 + -