
一、通信概述 Modbus Slave 是一款Modbus 从站模拟/测试软件,运行在 PC 上,用于模拟 Modbus 从站设备。在此场景中,S7-1200 作为 Modbus TCP 客户端(主站),Modbus Slave 作为Modbus TCP 服务器(从站)。 1.1 通信架构 1.2 通信角色说明(与 Modbus Poll 相反) 设备 | 角色 | 功能 | | S7-1200 | 客户端/主站 | 发起读/写请求 | | Modbus Slave | 服务器/从站 | 响应读/写请求 |
1.3 与 Modbus Poll 的区别 特性 | Modbus Poll | Modbus Slave | | 软件角色 | Modbus 主站 | Modbus 从站 | | S7-1200 角色 | 从站(MB_SERVER) | 主站(MB_CLIENT) | | 通信块 | MB_SERVER | MB_CLIENT | | 连接方式 | 被动监听 | 主动连接 | | 应用场景 | 测试 S7-1200 从站功能 | 测试 S7-1200 主站功能 |
1.4 通信特点 特性 | 说明 | 通信类型 | Modbus TCP(基于 TCP/IP) | 功能码 | 01/02/03/04/05/06/15/16 | 传输距离 | 标准 100 米(可扩展) | 通信周期 | 100ms ~ 1s 可调 | 端口号 | 默认 502 | 连接数 | S7-1200 最多支持 8 个 Modbus TCP 连接 |
--- 二、硬件与软件要求 2.1 软件要求 软件 | 最低版本 | 推荐版本 | 说明 | TIA Portal(博途) | V15.1 | V17/V18/V19 | S7-1200 组态 | S7-1200 固件 | V2.0 | V4.0+ | 支持 Modbus TCP 客户端 | Modbus Slave | V6.0 | V9.0+ | Modbus 从站测试软件 | MB_CLIENT 库 | V2.0+ | 最新版本 | TIA Portal 内置 | 操作系统 | Windows 7/10/11 | Windows 10/11 | 运行 Modbus Slave |
2.2 硬件要求 设备 | 型号 | 说明 | | S7-1200 | CPU 1212C/1214C/1215C/1217C | 带 PROFINET 接口 | | PC 电脑 | 任意 Windows PC | 运行 Modbus Slave | | 网线 | CAT5e 及以上 | 标准工业以太网线 | | 交换机 | 可选 | 多设备连接时使用 |
2.3 S7-1200 Modbus TCP 连接限制 S7-1200 型号 | 最大 Modbus TCP 连接数 | 说明 | CPU 1211C | 8 个 | 共享通信资源 | CPU 1212C | 8 个 | 共享通信资源 | CPU 1214C | 8 个 | 共享通信资源 | CPU 1215C | 8 个 | 共享通信资源 | CPU 1217C | 8 个 | 共享通信资源 |
--- 三、配置步骤(S7-1200 侧) 第一步:创建 TIA Portal 项目 打开TIA Portal软件 点击「创建新项目」,输入项目名称 选择「添加新设备」 第二步:添加 S7-1200 CPU 添加 PLC: 选择「控制器」→「SIMATIC S7-1200」→「CPU」 选择具体型号和固件版本 配置 PROFINET 接口: 进入「设备视图」→ 点击 CPU 上的 PROFINET 接口 在「属性」→「以太网地址」中设置: IP 地址:如 192.168.0.1 子网掩码:255.255.255.0 第三步:添加 Modbus TCP 通信块 打开程序块: 展开「程序块」→「系统块」 找到「Communication」→「Modbus TCP」 添加 MB_CLIENT 块: 拖拽「MB_CLIENT」到 OB1 或 FB/FC 中 系统会自动生成背景数据块(如 DB3) 配置 MB_CLIENT 参数: 参数 | 设置值 | 说明 | | CONNECT | 新建连接 | 指向 Modbus TCP 连接配置 | | MB_MODE | 0/1/2/3 | 0=保持,1=读取,2=写入,3=写多个 | | MB_ADDR | 1 | Modbus 从站地址 | | MODE | 0/1 | 0=保持寄存器,1=输入寄存器 | | DATA_ADDR | 0 | 起始寄存器地址 | | DATA_LEN | 10 | 读取/写入的数据长度 | | DATA_PTR | | 数据存储区指针 |
第四步:配置 Modbus TCP 连接 创建连接配置: 在「程序块」→「系统块」→「Modbus TCP」 右键「添加新连接」 配置连接参数: 参数 | 设置值 | 说明 | | 连接 ID | | 唯一连接标识 | | IP 地址 | 192.168.0.2 | Modbus Slave 的 IP 地址 | | 端口号 | 502 | Modbus TCP 默认端口 | | 连接类型 | TCP | 选择 TCP 连接 | | 主动建立连接 | 是 | PLC 作为客户端主动连接 |
第五步:创建数据块 创建 DB 块: 右键「程序块」→「添加新块」→「数据块」 命名为「Modbus_Data」 取消「优化的块访问」,使用绝对地址 定义变量: 变量名称 | 数据类型 | 地址 | 说明 | Read_Req | Bool | DB1.DBX0.0 | 读取请求 | Write_Req | Bool | DB1.DBX0.1 | 写入请求 | Read_Data | Array[0..99] Of Word | DB1.DBW2 | 读取数据区 | Write_Data | Array[0..99] Of Word | DB1.DBW202 | 写入数据区 | Comm_Status | Word | DB1.DBW402 | 通信状态 | Error_Code | Word | DB1.DBW404 | 错误代码 |
第六步:编写通信程序 // 主程序 OB1 或 FB// 调用 MB_CLIENT 块(读取)"MB_Client_Read"( CONNECT := 'Modbus_TCP_Connection', // 连接配置 MB_MODE := 1, // 1=读取 MB_ADDR := 1, // 从站地址 MODE := 0, // 0=保持寄存器 DATA_ADDR := 0, // 起始地址 DATA_LEN := 10, // 数据长度 DATA_PTR := P#"Modbus_Data".Read_Data[0], // 数据指针 REQ := "Modbus_Data".Read_Req, // 读取请求 BUSY => MB_Busy, // 忙标志 MODE => MB_Mode_Status, // 模式状态 DONE => MB_Done, // 完成标志 ERROR => MB_Error, // 错误标志 STATUS => MB_Status // 状态代码);// 调用 MB_CLIENT 块(写入)"MB_Client_Write"( CONNECT := 'Modbus_TCP_Connection', MB_MODE := 2, // 2=写入 MB_ADDR := 1, MODE := 0, DATA_ADDR := 10, // 写入起始地址 DATA_LEN := 10, DATA_PTR := P#"Modbus_Data".Write_Data[0], REQ := "Modbus_Data".Write_Req, BUSY => MB_Busy, DONE => MB_Done, ERROR => MB_Error, STATUS => MB_Status);第七步:编译并下载 编译项目: 点击「编译」→「编译全部」 检查是否有错误 下载 PLC 程序: 连接 S7-1200 PLC 下载程序到 PLC 将 PLC 切换到RUN 模式 --- 四、Modbus Slave 软件配置 第一步:安装 Modbus Slave 下载 Modbus Slave 软件(https://www.modbustools.com) 安装软件到 PC 启动 Modbus Slave 第二步:配置连接 点击「Connection」→「Connect」配置连接参数:参数 | 设置值 | 说明 | | Connection | Modbus TCP | 选择 TCP 连接 | | TCP/IP Setup | 点击配置 | 进入 IP 配置 | | IP Address | 192.168.0.2 | PC 的 IP 地址 | | Port | 502 | Modbus TCP 默认端口 | | Slave ID | 1 | Modbus 从站地址 |
第三步:配置数据区 点击「Setup」→「Slave Definition」配置从站参数:参数 | 设置值 | 说明 | | Slave ID | 1 | 从站地址(与 PLC 配置一致) | | Function | 03-Holding Register | 功能码 | | Address | 0 | 起始地址 | | Quantity | 100 | 寄存器数量 | | Scan Rate | 1000 ms | 扫描周期 |
第四步:设置初始数据 在数据显示窗口中: 双击寄存器单元格 输入初始值 按 Enter 确认 配置数据变化(可选): 点击「Display」→「Options」 设置数据自动递增/递减 模拟实际设备数据变化 第五步:开始监听 点击「Connection」→「Connect」开始监听 等待 PLC 主动连接 查看连接状态和数据交换 --- 五、数据交换格式详解 5.1 Modbus 功能码 功能码 | 名称 | S7-1200 映射 | 说明 | 01 | 读线圈 | %Q/M 区 | 读布尔输出 | 02 | 读离散输入 | %I/M 区 | 读布尔输入 | 03 | 读保持寄存器 | DB 块 | 读写字数据 | 04 | 读输入寄存器 | DB 块/IW 区 | 读字数据 | 05 | 写单线圈 | %Q/M 区 | 写布尔输出 | 06 | 写单寄存器 | DB 块 | 写字数据 | 15 | 写多线圈 | %Q/M 区 | 写多个布尔 | 16 | 写多寄存器 | DB 块 | 写多个字 |
5.2 地址映射表(典型配置) Modbus 地址 | 功能码 | Modbus Slave 地址 | S7-1200 地址 | 数据类型 | 说明 | 00001-00100 | 01 | 0-99 | DB1.DBX0.0 | Bool | 线圈 | 10001-10100 | 02 | 0-99 | DB1.DBX100.0 | Bool | 离散输入 | 40001-40100 | 03 | 0-99 | DB1.DBW200 | Word | 保持寄存器 | 30001-30100 | 04 | 0-99 | DB1.DBW400 | Word | 输入寄存器 |
5.3 Modbus TCP 报文格式 5.4 典型读写示例 读取保持寄存器: 请求:00 01 00 00 00 06 01 03 00 00 00 0A (事务 ID)(协议)(长度)(从站)(功能码)(起始地址)(数量)响应:00 01 00 00 00 17 01 03 14 [数据 20 字节]写入多寄存器: 请求:00 02 00 00 00 0D 01 10 00 0A 00 05 0A [数据 10 字节]响应:00 02 00 00 00 06 01 10 00 0A 00 05--- 六、编程示例 6.1 完整客户端程序(SCL) // 数据块 DB1 "Modbus_Client_Data"(取消优化块访问)DATA_BLOCK "Modbus_Client_Data"STRUCT // 控制命令 Read_Req : Bool; // DB1.DBX0.0 读取请求 Write_Req : Bool; // DB1.DBX0.1 写入请求 Read_Trigger : Bool; // DB1.DBX0.2 读取触发 Write_Trigger : Bool; // DB1.DBX0.3 写入触发 // 读取数据区 Read_Data : Array[0..99] Of Word; // DB1.DBW2 读取数据 // 写入数据区 Write_Data : Array[0..99] Of Word;// DB1.DBW202 写入数据 // 通信状态 Comm_Ready : Bool; // DB1.DBX402.0 通信就绪 Comm_Busy : Bool; // DB1.DBX402.1 通信忙 Comm_Error : Bool; // DB1.DBX402.2 通信错误 Error_Code : Word; // DB1.DBW404 错误代码 Status_Code : Word; // DB1.DBW406 状态代码 // 应用数据 Motor_Speed : Int; // DB1.DBW408 电机速度 Motor_Temp : Int; // DB1.DBW410 电机温度 Fault_Code : Word; // DB1.DBW412 故障代码 Part_Count : DInt; // DB1.DBD414 计数END_STRUCTEND_DATA_BLOCK// 功能块 FB_Modbus_ClientFUNCTION_BLOCK "FB_Modbus_Client"VAR // MB_CLIENT 实例 "MB_Client_Read" : MB_CLIENT; "MB_Client_Write" : MB_CLIENT; // 连接配置 "Modbus_TCP_Connection" : TCON_Modbus; // 状态变量 Read_Busy : Bool; Read_Done : Bool; Read_Error : Bool; Read_Status : Word; Write_Busy : Bool; Write_Done : Bool; Write_Error : Bool; Write_Status : Word; // 状态机 Step : Int := 0; Read_Timer : TON_TIME; Write_Timer : TON_TIME;END_VAR// 连接配置初始化"Modbus_TCP_Connection".connectionId := W161;"Modbus_TCP_Connection".connectionType := W161; // TCP"Modbus_TCP_Connection".activeEstablish := TRUE; // 主动连接"Modbus_TCP_Connection".remoteAddress := P#"192.168.0.2:502";// 状态机控制CASE Step OF 0: // 初始化 "Modbus_Client_Data".Comm_Ready := FALSE; Step := 1; 1: // 定期读取数据 Read_Timer(IN := TRUE, PT := T1S); // 1 秒读取一次 IF Read_Timer.Q AND NOT Read_Busy THEN "Modbus_Client_Data".Read_Trigger := TRUE; Read_Timer(IN := FALSE); END_IF; IF "Modbus_Client_Data".Read_Trigger THEN "MB_Client_Read"( CONNECT := 'Modbus_TCP_Connection', MB_MODE := 1, // 读取 MB_ADDR := 1, // 从站地址 MODE := 0, // 保持寄存器 DATA_ADDR := 0, // 起始地址 DATA_LEN := 10, // 读取 10 个寄存器 DATA_PTR := P#"Modbus_Client_Data".Read_Data[0], REQ := "Modbus_Client_Data".Read_Trigger, BUSY => Read_Busy, DONE => Read_Done, ERROR => Read_Error, STATUS => Read_Status ); IF Read_Done THEN "Modbus_Client_Data".Read_Trigger := FALSE; "Modbus_Client_Data".Comm_Ready := TRUE; "Modbus_Client_Data".Comm_Error := FALSE; // 数据处理 "Modbus_Client_Data".Motor_Speed := INT("Modbus_Client_Data".Read_Data[0]); "Modbus_Client_Data".Motor_Temp := INT("Modbus_Client_Data".Read_Data[1]); "Modbus_Client_Data".Fault_Code := "Modbus_Client_Data".Read_Data[2]; END_IF; IF Read_Error THEN "Modbus_Client_Data".Comm_Error := TRUE; "Modbus_Client_Data".Error_Code := Read_Status; END_IF; END_IF; Step := 2; 2: // 等待写入请求 IF "Modbus_Client_Data".Write_Req AND NOT Write_Busy THEN "Modbus_Client_Data".Write_Trigger := TRUE; Step := 3; ELSE Step := 1; END_IF; 3: // 执行写入 IF "Modbus_Client_Data".Write_Trigger THEN "MB_Client_Write"( CONNECT := 'Modbus_TCP_Connection', MB_MODE := 2, // 写入 MB_ADDR := 1, MODE := 0, DATA_ADDR := 10, // 写入起始地址 DATA_LEN := 5, // 写入 5 个寄存器 DATA_PTR := P#"Modbus_Client_Data".Write_Data[0], REQ := "Modbus_Client_Data".Write_Trigger, BUSY => Write_Busy, DONE => Write_Done, ERROR => Write_Error, STATUS => Write_Status ); IF Write_Done THEN "Modbus_Client_Data".Write_Trigger := FALSE; "Modbus_Client_Data".Write_Req := FALSE; Step := 1; END_IF; IF Write_Error THEN "Modbus_Client_Data".Comm_Error := TRUE; "Modbus_Client_Data".Error_Code := Write_Status; END_IF; END_IF; ELSE Step := 0;END_CASE;// 通信忙标志"Modbus_Client_Data".Comm_Busy := Read_Busy OR Write_Busy;"Modbus_Client_Data".Status_Code := Read_Status;6.2 数据映射处理 // 将 Modbus 读取的数据映射到 PLC 内部变量// 从 Modbus Slave 读取的数据处理"Motor_Speed_Setpoint" := INT("Modbus_Client_Data".Read_Data[0]);"Motor_Temp_Setpoint" := INT("Modbus_Client_Data".Read_Data[1]);"System_Fault" := "Modbus_Client_Data".Read_Data[2] <> 0;// 准备写入 Modbus Slave 的数据"Modbus_Client_Data".Write_Data[0] := WORD("Motor_Speed_Actual");"Modbus_Client_Data".Write_Data[1] := WORD("Motor_Current");"Modbus_Client_Data".Write_Data[2] := WORD("Part_Count_High");"Modbus_Client_Data".Write_Data[3] := WORD("Part_Count_Low");"Modbus_Client_Data".Write_Data[4] := "System_Status";// 触发写入IF "Data_Change_Flag" OR "Write_Timer".Q THEN "Modbus_Client_Data".Write_Req := TRUE;END_IF;6.3 多从站轮询示例 // 多 Modbus 从站轮询CASE "Poll_Index" OF 1: // 从站 1(Modbus Slave) "MB_Client_1"( CONNECT := 'Connection_1', MB_ADDR := 1, DATA_ADDR := 0, DATA_LEN := 10, REQ := "Poll_Trigger", DONE => "Poll_1_Done" ); 2: // 从站 2 "MB_Client_2"( CONNECT := 'Connection_2', MB_ADDR := 2, DATA_ADDR := 0, DATA_LEN := 10, REQ := "Poll_Trigger", DONE => "Poll_2_Done" ); 3: // 从站 3 "MB_Client_3"( CONNECT := 'Connection_3', MB_ADDR := 3, DATA_ADDR := 0, DATA_LEN := 10, REQ := "Poll_Trigger", DONE => "Poll_3_Done" );END_CASE;// 轮询切换"Poll_Timer"(IN := TRUE, PT := T500MS);IF "Poll_Timer".Q THEN "Poll_Index" := "Poll_Index" + 1; IF "Poll_Index" > 3 THEN "Poll_Index" := 1; END_IF; "Poll_Trigger" := TRUE; "Poll_Timer"(IN := FALSE);ELSE "Poll_Trigger" := FALSE;END_IF;--- 七、通信状态监控与诊断 7.1 MB_CLIENT 状态代码 状态代码 | 含义 | 解决方案 | | 无错误 | 正常 | | 连接超时 | 检查网络连接 | | 连接拒绝 | 检查 IP 和端口 | | 无连接 | 连接未建立 | | 连接断开 | 检查网络稳定性 | | 数据错误 | 检查寄存器地址 | | 功能码错误 | 检查功能码配置 | | 从站无响应 | 检查从站状态 | | 数据长度错误 | 检查数据长度配置 |
7.2 Modbus Slave 状态显示 显示 | 颜色 | 含义 | 数值显示 | 黑色 | 正常数据 | 数值显示 | 红色 | 通信错误 | 状态栏 | 绿色 | 连接正常 | 状态栏 | 红色 | 连接断开 | Tx 计数器 | 递增 | 接收请求 | Rx 计数器 | 递增 | 发送响应 | Err 计数器 | 递增 | 通信错误 |
7.3 TIA Portal 在线监控 在 TIA Portal 中查看 CPU 的「在线与诊断」 查看「通信」→「Modbus TCP」连接状态 查看通信错误信息 监控 DB 块数据变化 --- 八、常见问题与解决方案 问题现象 | 可能原因 | 解决方案 | 无法连接 Modbus Slave | IP 地址不在同一网段 | 检查并统一 IP 网段 | 连接超时 | 端口号错误 | 确认端口为 502 | 连接被拒绝 | Modbus Slave 未运行 | 检查软件是否启动 | 数据读取失败 | 寄存器地址错误 | 检查地址映射(注意偏移) | 功能码不支持 | 功能码配置错误 | 确认支持的功能码 | 从站地址错误 | MB_ADDR 不匹配 | 确认从站地址为 1 | 频繁通信中断 | 网线质量差 | 更换高质量网线 | 数据值异常 | 字节顺序错误 | 检查高低字节顺序 | DB 块访问失败 | 优化块访问启用 | 禁用优化块访问 | 多个请求冲突 | 未做互锁处理 | 添加状态机控制 | MB_CLIENT 报错 | 连接配置错误 | 检查 CONNECT 参数 | 防火墙阻止 | PC 防火墙设置 | 关闭防火墙或添加例外 | 读取数据不变 | Modbus Slave 数据未更新 | 检查 Slave 数据设置 |
--- 九、配置要点总结 配置项 | 关键要点 | 通信协议 | Modbus TCP(S7-1200 作为客户端) | IP 地址 | 同一网段,不能冲突 | 端口号 | 默认 502 | 从站地址 | Modbus Slave 中 Slave ID 通常为 1 | 连接配置 | MB_CLIENT 的 CONNECT 参数正确 | 数据指针 | 使用 P格式(如 PDB1.DBW0 BYTE 20) | DB 块优化 | 必须禁用优化块访问 | 功能码 | 01/02/03/04/05/06/15/16 | 地址映射 | 注意 Modbus 地址与 PLC 地址对应 | 状态机控制 | 避免多个请求同时发送 | 错误处理 | 添加通信错误处理和重试机制 | 防火墙 | PC 防火墙需允许 502 端口 | 网络连接 | 使用 CAT5e 及以上标准网线 |
--- 十、Modbus Poll vs Modbus Slave 对比 特性 | Modbus Poll | Modbus Slave | | 软件角色 | Modbus 主站 | Modbus 从站 | | S7-1200 角色 | 从站(MB_SERVER) | 主站(MB_CLIENT) | | 通信块 | MB_SERVER | MB_CLIENT | | 连接方式 | 被动监听 | 主动连接 | | IP 配置 | PLC 固定 IP,Poll 连接 PLC | Slave 固定 IP,PLC 连接 Slave | | 应用场景 | 测试 S7-1200 从站功能 | 测试 S7-1200 主站功能 | | 数据流向 | Poll 请求→PLC 响应 | PLC 请求→Slave 响应 |
--- 十一、推荐参考资料 资料名称 | 来源 | S7-1200 Modbus TCP 通信手册 | 西门子工业支持中心 | MB_CLIENT 功能块使用说明 | TIA Portal 帮助文档 | Modbus Slave 用户手册 | Modbus Tools 官网 | Modbus TCP 协议规范 | Modbus 组织官网 |
--- 十二、总结 S7-1200 与 Modbus Slave 的通信是Modbus TCP 主站测试的经典方案,具有以下优势: 优势 | 说明 | 标准协议 | Modbus TCP 是开放标准,兼容性好 | 配置简单 | TIA Portal 内置 MB_CLIENT 块 | 测试方便 | Modbus Slave 直观显示数据 | 成本优化 | 无需额外通信模块 | 扩展灵活 | 支持多个从站连接 | 兼容性好 | 支持标准 Modbus TCP 服务器 |
配置流程简图 重要提示 S7-1200 作为 Modbus TCP 客户端,主动发起连接IP 地址必须在同一网段,不能冲突端口号默认为 502,如有修改需同步配置DB 块必须禁用优化块访问,使用绝对地址Modbus Slave 中 Slave ID 通常为1PC 防火墙需允许 502 端口,否则连接会被阻止使用状态机控制通信,避免多个请求冲突注意地址映射关系,Modbus 地址与 PLC 地址要对应 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |