西门子的Modbus_TCP/IP FB(功能块)封装主要用于实现与支持Modbus TCP/IP协议的设备之间的通信。这种通信方式基于以太网,能够有效集成不同制造商生产的设备进入一个统一的自动化系统中,增强了系统的互操作性和扩展性。一、主要应用场合工业自动化:在制造业中,不同类型的设备需要进行数据交换和控制命令传递。通过使用Modbus TCP/IP FB块,可以方便地将各种支持该协议的设备连接到PLC(可编程逻辑控制器),如西门子S7系列,实现对生产流程的监控和管理。 楼宇自动化:用于HVAC(暖通空调)、照明系统、安防系统等的集中管理和控制,提高能效和居住舒适度。 能源管理系统:监测和控制系统中的电表、水表、气表等计量装置,帮助用户优化能源使用效率,降低运营成本。 环境监测:收集温度、湿度、空气质量等环境参数的数据,适用于温室、实验室等需要精确控制环境条件的场所。
二、意义简化开发过程:开发者无需深入了解Modbus TCP/IP协议的具体细节,只需调用相应的FB块即可快速实现通信功能,节省了开发时间和成本。 增强兼容性:由于Modbus TCP/IP是一种开放的标准协议,广泛应用于多种设备和系统中,因此采用这一协议有助于构建更加开放和灵活的自动化解决方案。 提高可靠性:通过标准化的通信机制,确保了数据传输的准确性和稳定性,减少了因通信故障导致的生产中断风险。 便于维护和升级:模块化的程序设计使得系统更容易维护,并且可以根据需求方便地添加或更换设备,提升了系统的可扩展性。
三、FB块封装 //初始化连接参数 #s_TCON_Param.InterfaceId := #i_InterfaceId; //硬件标识符 #s_TCON_Param.ID := #i_ID; //引用该连接(值范围: 1 - 4095)。 #s_TCON_Param.ConnectionType := b#16#11; //B#16#11:TCP 19=UDP #s_TCON_Param.ActiveEstablished := #i_Active; //FALSE:被动建立;TRUE:主动建立 //远程IP=电脑IP地址 #s_TCON_Param.RemoteAddress.ADDR[1] := #i_RemoteIP1; #s_TCON_Param.RemoteAddress.ADDR[2] := #i_RemoteIP2; #s_TCON_Param.RemoteAddress.ADDR[3] := #i_RemoteIP3; #s_TCON_Param.RemoteAddress.ADDR[4] := #i_RemoteIP4; //远程端口 //PLC客户端需要远程端口;PLC服务器远程端口必须为0,PLC变更模式CPU需要重启 IF #i_Active THEN #s_TCON_Param.RemotePort := #i_RemotePort; ELSE #s_TCON_Param.RemotePort := 0; END_IF; //本地端口 #s_TCON_Param.LocalPort := #i_LocalPort;
//======================== 连接判断 ============================= IF #s_TCON_Ok = false AND #s_EndConnect = false AND #i_Connect THEN //开始连接准备信号 与 断开连接信号 #s_StartConnect := true; //启动连接 IF #TCON_Instance.DONE OR #TCON_Instance.ERROR THEN //连接ok后 false连接信号 #s_StartConnect := false; #s_TCON_Ok := true; END_IF; END_IF;
//重复连接信号启动 #s_ConnectOnline(IN := #s_TCON_Ok AND #s_StartConnect = false AND (#TRCV_Instance.ERROR OR #TDIAG_Param.State <> 16#04), PT := T#1S); //延时启动连接 IF #s_ConnectOnline.Q THEN #s_StartConnect := true; END_IF;
//重复连接信号停止 #s_ConnectOffline(IN := #s_StartConnect, PT := T#1S); //延时断开 IF #s_ConnectOffline.Q THEN #s_StartConnect := FALSE; END_IF;
//断开连接重新链接判断 //(远程IP)或(远程端口)变更 就执行 断开连接 #r_trigDisconnect(CLK := NOT #i_Connect);
IF (#s_LastIP1 <> #i_RemoteIP1 OR #s_LastIP2 <> #i_RemoteIP2 OR #s_LastIP3 <> #i_RemoteIP3 OR #s_LastIP4 <> #i_RemoteIP4 OR #s_LastRemPort <> #i_RemotePort OR #r_trigDisconnect.Q) THEN #s_TCON_Ok := false; //开始连接准备信号 #s_StartConnect := false;//开始连接信号 #s_EndConnect := true; //断开连接信号 END_IF; IF #TDISCON_Instance.DONE OR #TDISCON_Instance.ERROR THEN //完成信号 与 错误 #s_EndConnect := false; #s_LastIP1 := #i_RemoteIP1; #s_LastIP2 := #i_RemoteIP2; #s_LastIP3 := #i_RemoteIP3; #s_LastIP4 := #i_RemoteIP4; #s_LastRemPort := #i_RemotePort;
END_IF; //#s_EndConnect := false; //开始连接 ===================================================================== #TCON_Instance(REQ := #s_StartConnect // IN: BOOL , ID := #i_ID // IN: WORD , CONNECT := #s_TCON_Param // INOUT: ANY );
//断开连接 ===================================================================== #TDISCON_Instance(REQ := #s_EndConnect // IN: BOOL , ID := #i_ID // IN: WORD );
//接收数据 ===================================================================== #TRCV_Instance(EN_R := #i_Recv // IN: BOOL , ID := #i_ID // IN: WORD , LEN := #i_RecvNum // IN: INT , ADHOC := TRUE , DATA := #io_RBuff // INOUT: ANY );
//发送数据 ===================================================================== #TSEND_Instance(REQ := #i_Send // IN: BOOL , ID := #i_ID // IN: WORD , LEN := #i_SendNum // IN: INT , DATA := #io_SBuff // INOUT: ANY );
//检查连接 ===================================================================== #TDIAG_Instance(REQ := #s_TdiagReq // IN: BOOL , ID := #i_ID // IN: WORD , RESULT := #TDIAG_Param // INOUT: ANY ); // 0.5S 延时检查连接 #s_ConnectCheckOn(IN := #s_TdiagReq = FALSE, PT := T#500MS);
IF #s_ConnectCheckOn.Q THEN #s_TdiagReq := TRUE; END_IF;
#s_ConnectCheckOff(IN := #s_TdiagReq, PT := T#500MS);
IF #s_ConnectCheckOff.Q THEN #s_TdiagReq := FALSE; END_IF;
// 接收错误 IF #TRCV_Instance.ERROR OR #TDIAG_Param.State <> 16#04 OR NOT #i_Connect THEN #o_Connected := false; ELSE #o_Connected := true; END_IF;
#o_SendEnd := #TSEND_Instance.DONE; #o_RecvEnd := #TRCV_Instance.NDR; //接收数据 IF #TRCV_Instance.NDR THEN #o_RecvNum := UDINT_TO_INT(#TRCV_Instance.RCVD_LEN); END_IF;
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |