📄 protocol.c
字号:
*(ModbusBuff+2) = HIBYTE(DDStartAddr); *(ModbusBuff+3) = LOBYTE(DDStartAddr); *(ModbusBuff+4) = 0x00; *(ModbusBuff+5) = 0x08; CRCValue = CRC16(ModbusBuff, 6); *(ModbusBuff+6) = HIBYTE(CRCValue); *(ModbusBuff+7) = LOBYTE(CRCValue); ret = 8; } else { ret = 0; } return ret;}void GEPLC_Command_Handle(int iPort,int iNetGroup,int iConnect,unsigned char *ModbusBuff,unsigned short *CommandBuff,int iLen){ float TempYT; unsigned long ulInf; unsigned long TempDD; unsigned long HiWord,LoWord; int DO_Num, iDO, PER_NUM = 64,DdCount = 4; int i, k, m, nRecv, nLen, iGroup, ret = 0; unsigned short CRC16Result,Temp[2]; unsigned char ucVSQ,ucSPI,ConLen,ucLen,ucSect = 1; unsigned char TempYt[4],SendBuff[128]; unsigned char RetFlag[2],IEC104DataBuf_M[256]; unsigned char TempDgt[512],COM_Recv[256],DD_Buff[36]; unsigned char ucADDR = ModbusBuff[0]; unsigned char ucSECT = CommandBuff[0]; if (iLen == 8)//电度量 { for(k=0;k<3;k++) { COMM_SendBuff(iPort,ModbusBuff, iLen); SYS_Delay(200); ret = Read_Modbus_Frame(iPort,ucADDR,COM_Recv); if(ret>0) { ret = IEC_PackPowerHead_104( IEC104DataBuf_M, ucADDR, ucSect, 5);//回答电度量冻结确认 CONN_Send104Data(iNetGroup, iConnect, IEC104DataBuf_M, ret ); SYS_Delay(10); for(i = 0; i < DdCount; i++) { HiWord = COM_Recv[3 + 4 * i]*256 + COM_Recv[4 + 4 * i] ; LoWord = COM_Recv[5 + 4 * i]*256 + COM_Recv[6 + 4 * i] ; TempDD = HiWord*0x10000 + LoWord ; Temp[0]=TempDD & 0xFFFF; Temp[1]=(TempDD >> 16) & 0xFFFF; DD_Buff[0 + i * 5] = LOBYTE(Temp[0]); DD_Buff[1 + i * 5] = HIBYTE(Temp[0]); DD_Buff[2 + i * 5] = LOBYTE(Temp[1]); DD_Buff[3 + i * 5] = HIBYTE(Temp[1]); DD_Buff[4 + i * 5] = i; } ucVSQ = 0x80 | DdCount; ucLen = DdCount * 5; ret = IEC_PackFrame_104(IEC104DataBuf_M, 15, ucVSQ, 37, ucADDR, 1, 1, ucLen, DD_Buff); CONN_Send104Data(iNetGroup, iConnect, IEC104DataBuf_M, ret ); SYS_Delay(10); ret = IEC_PackPowerEnd_104( IEC104DataBuf_M, ucADDR, ucSect, 5); //回答电度量数据结束 CONN_Send104Data(iNetGroup, iConnect, IEC104DataBuf_M, ret ); SYS_Delay(10); break; } SYS_Delay(200); } } if(iLen==9)//总召唤命令,上送遥信 { ret = IEC_PackInspectHead_104( IEC104DataBuf_M, ucADDR, ucSECT );//回答确认命令 CONN_Send104Data(iNetGroup,iConnect,IEC104DataBuf_M,ret); SYS_Delay(10); switch(ucSECT) { case 0: //上送通信状态 ucSPI = SubDevice[iPort].SubStations[0].sub_state; ret =IEC_PackNode_104(IEC104DataBuf_M,ucADDR,IEC104_COT_M_introgen,ucSPI); CONN_Send104Data(iNetGroup,iConnect,IEC104DataBuf_M,ret); SYS_Delay(10); break; case 2://上送遥信DI量,DI个数为512 nLen=Get_GEPLC_DgtFrame(SendBuff,ucADDR,DI,iPort); for(k=0;k<3;k++) { COMM_SendBuff(iPort,SendBuff,nLen); SYS_Delay(200); nRecv = Read_Modbus_Frame(iPort, ucADDR, COM_Recv); if ( nRecv > 0 ) { for(i=0;i<512;i++) TempDgt[i] = GetDigital(COM_Recv+3,i)+1; for( m=0; m<(512/PER_NUM); m++ ) { ucVSQ = 0x80 | PER_NUM ; ConLen = PER_NUM ; ulInf = PER_NUM*m+1 ; ret=IEC_PackFrame_104(IEC104DataBuf_M,3/*类别标识*/,ucVSQ/*可变结构限定词*/,20/*传输原因*/,ucADDR/*设备地址*/, 0x02/*扇区号*/,ulInf/*信息地址*/,ConLen/*要转换的字节数*/,&TempDgt[ulInf-1]); CONN_Send104Data(iNetGroup,iConnect,IEC104DataBuf_M,ret); SYS_Delay(10); } break; } SYS_Delay(200); } break; case 3://上送遥信量 nLen = Get_GEPLC_DgtFrame(SendBuff,ucADDR,DO,iPort); for(k=0;k<3;k++) { COMM_SendBuff(iPort,SendBuff,nLen) ; SYS_Delay(200) ; nRecv = Read_Modbus_Frame(iPort, ucADDR, COM_Recv) ; if ( nRecv > 0 ) { DO_Num = SubDevice[iPort].SubStations[0].sub_YX_NUM; for(i=0;i<DO_Num;i++) TempDgt[i] = GetDigital(COM_Recv+3,i)+1 ; iGroup = DO_Num/PER_NUM ; for(m=0;m<iGroup;m++) { ucVSQ = 0x80 | PER_NUM ; ConLen = PER_NUM ; ulInf = PER_NUM*m+1 ; ret = IEC_PackFrame_104(IEC104DataBuf_M,3/*类别标识*/,ucVSQ/*可变结构限定词*/,20/*传输原因*/,ucADDR/*设备地址*/, 0x03/*扇区号*/,ulInf/*信息地址*/,ConLen/*要转换的字节数*/,&TempDgt[ulInf-1]); CONN_Send104Data(iNetGroup,iConnect,IEC104DataBuf_M,ret); SYS_Delay(10); } if(DO_Num%PER_NUM) { iDO = DO_Num%PER_NUM ; ucVSQ = 0x80 | iDO ; ConLen = iDO ; ulInf = PER_NUM*m+1 ; ret=IEC_PackFrame_104(IEC104DataBuf_M,3/*类别标识*/,ucVSQ/*可变结构限定词*/,20/*传输原因*/,ucADDR/*设备地址*/, 0x03/*扇区号*/,ulInf/*信息地址*/,ConLen/*要转换的字节数*/,&TempDgt[ulInf-1]); CONN_Send104Data(iNetGroup,iConnect,IEC104DataBuf_M,ret); SYS_Delay(10); } break; } SYS_Delay(200); } break; default : break; } ret = IEC_PackInspectEnd_104( IEC104DataBuf_M, ucADDR, ucSECT );//回答结束报文 CONN_Send104Data(iNetGroup,iConnect,IEC104DataBuf_M,ret); SYS_Delay(10); } if (iLen==13)//遥控选择命令 { for (k=0;k<3;k++) { COMM_SendBuff(iPort,ModbusBuff, iLen); SYS_Delay(200); ret = Read_Modbus_Frame(iPort, ucADDR, COM_Recv); if(ret>0) { SYS_Delay(100); //组查询遥控返校信息的报文,查询返校标志位的信息// SendBuff[0] = ucADDR; SendBuff[1] = 0x03; SendBuff[2] = 0x3; SendBuff[3] = 0x01; SendBuff[4] = 0x00; SendBuff[5] = 0x01; CRC16Result = CRC16(SendBuff, 6); SendBuff[6] = HIBYTE(CRC16Result); SendBuff[7] = LOBYTE(CRC16Result); ////////////组查询遥控返校信息的报文//////////// COMM_SendBuff(iPort,SendBuff, 8); SYS_Delay(200); ret = Read_Modbus_Frame(iPort,ucADDR,COM_Recv); if (ret>0) { ulInf = CommandBuff[1]; if (COM_Recv[4]==0xF0) { //遥控选择成功 RetFlag[0]=CommandBuff[2]; ret=IEC_PackFrame_104(IEC104DataBuf_M,46/*类别标识*/,1/*可变结构限定词*/,7/*传输原因*/,ucADDR/*设备地址*/, 0x03/*扇区号*/,ulInf/*信息地址*/,1/*要转换的字节数*/,RetFlag); CONN_Send104Data(iNetGroup,iConnect,IEC104DataBuf_M,ret); SYS_Delay(10); } else if (COM_Recv[4]==0x0F) { //遥控选择失败 RetFlag[0] = CommandBuff[2]; ret = IEC_PackFrame_104(IEC104DataBuf_M,46/*类别标识*/,1/*可变结构限定词*/,0x47/*传输原因*/,ucADDR/*设备地址*/, 003/*扇区号*/,ulInf/*信息地址*/,1/*要转换的字节数*/,RetFlag); CONN_Send104Data(iNetGroup,iConnect,IEC104DataBuf_M,ret); SYS_Delay(10); } else { //其他情况(标志位不是成功标志),选择失败 RetFlag[0] = CommandBuff[2]; ret = IEC_PackFrame_104(IEC104DataBuf_M,46/*类别标识*/,1/*可变结构限定词*/,0x47/*传输原因*/,ucADDR/*设备地址*/, 0x03/*扇区号*/,ulInf/*信息地址*/,1/*要转换的字节数*/,RetFlag); CONN_Send104Data(iNetGroup,iConnect,IEC104DataBuf_M,ret); SYS_Delay(10); } } break; } SYS_Delay(200); } } if (iLen==11)//遥控执行、撤销命令 { for (k=0;k<3;k++) { COMM_SendBuff(iPort,ModbusBuff, iLen); SYS_Delay(200); ret = Read_Modbus_Frame(iPort,ucADDR,COM_Recv); if(ret>0) { if (ModbusBuff[8]==0x80)//执行 { ulInf = CommandBuff[1]; RetFlag[0] = CommandBuff[2]; ret=IEC_PackFrame_104(IEC104DataBuf_M,46/*类别标识*/,1/*可变结构限定词*/,7/*传输原因*/,ucADDR/*设备地址*/, 0x03/*扇区号*/,ulInf/*信息地址*/,1/*要转换的字节数*/,RetFlag); CONN_Send104Data(iNetGroup,iConnect,IEC104DataBuf_M,ret); SYS_Delay(10); } if (ModbusBuff[8]==0xA0)//取消 { ulInf = CommandBuff[1]; RetFlag[0] = CommandBuff[2]; ret=IEC_PackFrame_104(IEC104DataBuf_M,46/*类别标识*/,1/*可变结构限定词*/,9/*传输原因*/,ucADDR/*设备地址*/, 0x03/*扇区号*/,ulInf/*信息地址*/,1/*要转换的字节数*/,RetFlag); CONN_Send104Data(iNetGroup,iConnect,IEC104DataBuf_M,ret); SYS_Delay(10); } break; } SYS_Delay(200); } } if (iLen==14)//直控 { for (k=0;k<3;k++) { COMM_SendBuff(iPort,ModbusBuff, iLen-1); SYS_Delay(200); ret = Read_Modbus_Frame(iPort,ucADDR,COM_Recv); if ( ret>0 ) { //直控执行结束,返回确认报文 ulInf=CommandBuff[1]; RetFlag[0]=CommandBuff[2]; ret=IEC_PackFrame_104(IEC104DataBuf_M,46/*类别标识*/,1/*可变结构限定词*/,7/*传输原因*/,ucADDR/*设备地址*/, 0x03/*扇区号*/,ulInf/*信息地址*/,1/*要转换的字节数*/,RetFlag/*要转换的字节的起始地址*/ ); CONN_Send104Data(iNetGroup,iConnect,IEC104DataBuf_M,ret); SYS_Delay(10); //直控过程结束,返回报文// ret=IEC_PackFrame_104(IEC104DataBuf_M,46/*类别标识*/,1/*可变结构限定词*/,10/*传输原因*/,ucADDR/*设备地址*/,// 0x03/*扇区号*/,ulInf/*信息地址*/,1/*要转换的字节数*/,RetFlag/*要转换的字节的起始地址*/ );// CONN_Send104Data(iNetGroup,iConnect,IEC104DataBuf_M,ret); // SYS_Delay(10); break; } SYS_Delay(200); } } if (iLen==15)//遥调执行 { for (k=0;k<3;k++) { COMM_SendBuff(iPort,ModbusBuff, iLen); SYS_Delay(200); ret = Read_Modbus_Frame(iPort,ucADDR,COM_Recv); if ( ret>0) { //遥调执行结束,返回确认报文 ulInf = CommandBuff[1]; *(ModbusBuff+13)=0; ret=IEC_PackFrame_104(IEC104DataBuf_M,50/*类别标识*/,1/*可变结构限定词*/,7/*传输原因*/,ucADDR/*设备地址*/, 0x03/*扇区号*/,ulInf/*信息地址*/,5/*要转换的字节数*/,(ModbusBuff+9)/*要转换的字节的起始地址*/ ); CONN_Send104Data(iNetGroup,iConnect,IEC104DataBuf_M,ret); SYS_Delay(10); //遥调过程结束,返回报文 ret=IEC_PackFrame_104(IEC104DataBuf_M,50/*类别标识*/,1/*可变结构限定词*/,10/*传输原因*/,ucADDR/*设备地址*/, 0x03/*扇区号*/,ulInf/*信息地址*/,5/*要转换的字节数*/,(ModbusBuff+9)/*要转换的字节的起始地址*/ ); CONN_Send104Data(iNetGroup,iConnect,IEC104DataBuf_M,ret); SYS_Delay(10); break; } SYS_Delay(200); } } if (iLen==20)//遥调选择或遥调撤消 { if (ModbusBuff[8]==6)//遥调选择 { ulInf = ModbusBuff[14]*0x10000+ModbusBuff[13]*0x100+ModbusBuff[12]; TempYt[0] = *(ModbusBuff+15); TempYt[1] = *(ModbusBuff+16); TempYt[2] = *(ModbusBuff+17); TempYt[3] = *(ModbusBuff+18); memcpy(&TempYT,TempYt,4); if ( (TempYT<0.0)||(TempYT>204800.0) ) //如果遥调值不在0-32767之间,返回选择失败信息 ret=IEC_PackFrame_104(IEC104DataBuf_M,50/*类别标识*/,1/*可变结构限定词*/,0x47/*传输原因*/,ModbusBuff[11]/*设备地址*/, 0x03/*扇区号*/,ulInf/*信息地址*/,5/*要转换的字节数*/,(ModbusBuff+15) ); else ret=IEC_PackFrame_104(IEC104DataBuf_M,50/*类别标识*/,1/*可变结构限定词*/,7/*传输原因*/,ModbusBuff[11]/*设备地址*/, 0x03/*扇区号*/,ulInf/*信息地址*/,5/*要转换的字节数*/,(ModbusBuff+15) ); CONN_Send104Data(iNetGroup,iConnect,IEC104DataBuf_M,ret); SYS_Delay(10); } if (ModbusBuff[8]==8)//遥调撤消 { ulInf=ModbusBuff[14]*0x10000+ModbusBuff[13]*0x100+ModbusBuff[12]; ret=IEC_PackFrame_104(IEC104DataBuf_M,50/*类别标识*/,1/*可变结构限定词*/,9/*传输原因*/,ModbusBuff[11]/*设备地址*/, 0x03/*扇区号*/,ulInf/*信息地址*/,5/*要转换的字节数*/,(ModbusBuff+15) ); CONN_Send104Data(iNetGroup,iConnect,IEC104DataBuf_M,ret); SYS_Delay(10); } } if (iLen==19)//校时命令 { for(k=0;k<3;k++) { COMM_SendBuff(iPort,ModbusBuff, iLen); SYS_Delay(200); ret = Read_Modbus_Frame(iPort,ucADDR,COM_Recv); if(ret>0) { break; } SYS_Delay(200); } }}void Check_SOEInfo(int iPort,unsigned short SOE_Pointer){ unsigned char old_SOEPointer=SubDevice[iPort].SubStations[0].sub_DataTemp[0]; if((SOE_Pointer==0)||(SOE_Pointer>TotalSOE)) return;//SOE指针不能大于16 if(SOE_Pointer != old_SOEPointer) { if(SOE_Pointer>old_SOEPointer) { Process_SOEInf(iPort,old_SOEPointer,SOE_Pointer-old_SOEPointer); } else { Process_SOEInf(iPort,old_SOEPointer,TotalSOE-old_SOEPointer); Process_SOEInf(iPort,0,SOE_Pointer); } }}void Process_SOEInf(int iPort,unsigned short SOE_Pointer,int nChange){ int k,ret; unsigned long ulInf; unsigned short TempMs,StartAddr; unsigned char SendBuff[10],TempBuff[16],COM_Recv[256],IEC104DataBuf_M[256]; unsigned short CRC16Result; unsigned char ucADDR = SubDevice[iPort].SubStations[0].sub_address; SYS_Delay(100); //组查询SOE信息的报文// SendBuff[0] = ucADDR ; SendBuff[1] = 0x03; StartAddr = SOEStartAddr+SOE_Pointer*5;//每条SOE信息占用5个寄存器 SendBuff[2] = (unsigned char)(StartAddr/256); SendBuff[3] = (unsigned char)(StartAddr%256); SendBuff[4] = 0x00; SendBuff[5] = 5*nChange; CRC16Result = CRC16(SendBuff, 6); SendBuff[6] = HIBYTE(CRC16Result); SendBuff[7] = LOBYTE(CRC16Result); ////////////组查询SOE信息的报文//////////// COMM_SendBuff(iPort,SendBuff, 8); SYS_Delay(200); ret = Read_Modbus_Frame(iPort,ucADDR,COM_Recv); if ((ret>0) && (COM_Recv[1]==0x03)) { for(k=0;k<nChange;k++) { TempBuff[0] = COM_Recv[4+k*10]+1; //信息元素(双点) TempBuff[1] = TempBuff[2] = 0; //相对时间 TempMs = COM_Recv[7+k*10]*1000 + COM_Recv[5+k*10]*256 + COM_Recv[6+k*10]; TempBuff[3] = (unsigned char)(TempMs&0xff); //毫秒低 TempBuff[4] = (unsigned char)(TempMs>>8); //毫秒高 TempBuff[5] = COM_Recv[8+k*10]; //分 TempBuff[6] = COM_Recv[9+k*10]; //时 TempBuff[7] = COM_Recv[10+k*10]; //日 TempBuff[8] =COM_Recv[11+k*10]; //月 TempBuff[9] = COM_Recv[12+k*10]; //年 ulInf = COM_Recv[3+k*10]; //SOE序号对应后台的信息体地址 ret=IEC_PackFrame_104(IEC104DataBuf_M,38/*类别标识*/,1/*可变结构限定词*/,3/*传输原因*/,ucADDR/*设备地址*/, 0x01/*扇区号*/,ulInf/*信息地址*/,10/*要转换的字节数*/,&TempBuff[0]); CONN_Broad104Data(IEC104DataBuf_M,ret); SYS_Delay(10); SubDevice[iPort].SubStations[0].sub_DataTemp[0]++; if(SubDevice[iPort].SubStations[0].sub_DataTemp[0]>TotalSOE) SubDevice[iPort].SubStations[0].sub_DataTemp[0]=1; } }} void Process_GEPLC_Recv(int iPort, unsigned char *pData)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -