简介:本资源是一份面向工业自动化工程师与PLC初学者的西门子S7-1200 PUT&GET通信实战教程,聚焦PROFINET环境下两台S7-1200 PLC间高效、稳定的数据交互问题,特别适用于需实现跨设备数据同步、分布式控制或项目升级迁移的工程场景。教程完整覆盖同一项目与不同项目两种典型组态方式,详解Step7 V13 SP1软件中S7连接创建、TSAP配置、非优化数据块定义(10字节数组)、PUT/GET指令调用及状态监控等核心操作,并附带详细参数说明与在线连接验证截图。资源为1个4.28MB的Word文档(.doc),内容结构清晰,含硬件配置清单、网络视图操作指引、OB1编程示例、功能块参数表及实际监控结果图,便于边学边练、快速复现。目前已有11298人学习下载,是掌握S7-1200单边S7通信从原理到落地的关键参考资料。
1. 西门子S7-1200 PUT&GET通信:不是“配通就行”,而是“连对、写对、防错三者缺一不可”的硬核实操
你手上有两台S7-1200——一台V4.1,一台V2.0,网线一插,STEP 7 V13里拖个S7连接、调两个PUT/GET块,监控一看DB数据没动?别急着怀疑网线或IP,90%的翻车点根本不在物理层,而在三个被文档轻描淡写带过的“隐性开关”:非优化访问必须关、服务器端保护策略默认锁死、TSAP号在跨项目时必须手动对齐。这不是理论课,是某高校自动化实验室连续三天反复下载固件、重刷IP、抓包验证后才抠出来的血泪经验。本教程专治“能连上但传不了数据”的玄学现场,覆盖同一项目内双站协同与跨项目独立部署两种真实产线场景,所有操作均基于V2.0/V4.1混合固件环境实测通过。适合刚从TIA Portal转战STEP 7 V13的工程师、需要快速打通旧产线PLC间数据通道的维护人员,以及正在做毕业设计需复现S7底层通信逻辑的学生。它不讲PROFINET协议栈分层,只告诉你哪一步漏了会导致STATUS=16#80B1(连接拒绝),哪一行参数错位会让NDR永远为0。
2. S7通信底层逻辑与选型依据:为什么必须用PUT/GET,而不是IO通信或开放式用户通信?
2.1 PUT/GET的本质:S7单边通信的“无状态搬运工”,不是“双向会话”
S7-1200的S7通信能力常被误读为“类似TCP连接”,实际它是西门子定义的应用层单向数据搬运协议,核心特征有三:
- 单边组态:仅客户端(主动方)需配置连接、调用指令;服务器端(被动方)只需开放数据区、允许访问,不参与连接建立过程;
- 无连接维持:每次PUT/GET执行即发起一次完整S7报文交互(含握手、数据传输、确认),不维持长连接;
- 地址驱动:数据流向由指令中
ADDR_1(目标地址)和SD_1/RD_1(源/目的数据区)共同决定,与PLC物理位置无关。
提示:这解释了为何跨项目通信时,服务器端无需任何“连接配置”——它只响应来自指定IP+TSAP的合法读写请求,像一个静默的数据库接口。
2.2 为什么不用PROFINET IO?——实时性、拓扑与权限的硬约束
当两台S7-1200同处一个控制柜,有人会问:“直接走IO通信不行吗?”答案是:可以,但代价极高。
- 实时性冗余:IO通信要求严格等时循环(如1ms),而PUT/GET单次传输耗时约5~15ms,对非运动控制类数据(如参数同步、报警日志)已足够,且不占用IO周期;
- 拓扑自由:IO通信强制主从结构(一台作IO控制器,另一台作IO设备),而PUT/GET支持任意客户端→服务器映射,甚至一对多广播(需多实例调用);
- 权限穿透:IO通信需双方在同一个TIA项目中完成设备角色分配,而PUT/GET可穿透项目边界,实现不同工程团队独立开发的PLC间对接——这正是产线升级中“新旧系统并行运行”的刚需。
2.3 固件版本差异:V2.0与V4.1的兼容性断层在哪里?
项目正文明确列出V2.0与V4.1混用场景,这不是凑数,而是踩坑高发区:
- V2.0服务器端:默认允许PUT/GET访问,无需额外设置(但需确保数据块为非优化访问);
- V4.0+服务器端:安全机制升级,默认禁止所有远程PUT/GET请求,必须手动勾选“允许从远程伙伴使用PUT/GET通信访问”(见图14)。此开关位于设备组态→属性→常规→保护→连接机制,未开启则客户端始终收到
ERROR=1, STATUS=16#80B1; - 客户端兼容性:V4.1客户端可向下兼容V2.0服务器,但V2.0客户端无法连接V4.0+服务器(因TSAP协商机制变更),故项目中客户端必须为V4.1或更高版本。
2.4 地址空间映射:TSAP号不是“随便填”,而是S7通信的“门牌号”
TSAP(Transport Service Access Point)是S7协议中标识服务端口的关键字段,其格式为XX.YY:
XX:子网号(S7-1200固定为03,代表PROFINET接口);YY:服务实例号(S7-1200预置两个:00用于S7通信,01保留)。
关键细节:
- 同一项目内组态时,STEP 7自动为服务器分配TSAP
03.00,客户端调用PUT/GET时无需指定,由连接ID隐式绑定; - 跨项目时,客户端必须在连接属性中显式填写服务器TSAP
03.00(见图12),若填错(如03.01)或留空,服务器将直接丢弃请求,客户端STATUS返回16#8104(无效TSAP); - 此值与IP地址独立,同一IP下可存在多个TSAP(如同时启用S7通信与OPC UA),但S7-1200硬件仅开放
03.00。
3. 同一项目内双S7-1200通信:从网络组态到指令调用的端到端实操
3.1 STEP 7 V13项目创建与双站组态:IP地址规划是后续所有步骤的基石
创建新项目后,按顺序添加两个S7-1200设备:
- Client站:选择CPU 1214C DC/DC/DC,固件V4.1,设备名称设为
S7-1200_Client,IP地址设为192.168.0.10(子网掩码255.255.255.0); - Server站:选择CPU 1214C DC/DC/DC,固件V2.0,设备名称设为
S7-1200_Server,IP地址设为192.168.0.12。
注意:两站必须在同一子网(此处为
192.168.0.x),且IP不能与PC编程口冲突。若PC网卡IP为192.168.0.100,则PLC IP需避开该范围。
3.2 网络视图中建立S7连接:连接ID(Local ID)是PUT/GET指令的“身份证”
进入“设备视图”→切换至“网络视图”,执行以下操作:
- 点击左上角“连接”图标 → 在连接类型中选择“S7连接”;
- 拖拽连接线从
S7-1200_ClientCPU图标至S7-1200_ServerCPU图标; - 右键连接线 → “添加新连接” → 在弹窗中确认“连接对象”为
S7-1200_Server,勾选“主动建立连接”; - 点击“确定”生成连接,此时连接列表中出现
S7_Connection_1。
双击该连接,在属性窗口中确认:
- 常规页:本地设备为
S7-1200_Client,远程设备为S7-1200_Server,IP地址正确; - 本地ID页:
W#16#100(十六进制100,即十进制256),此值将作为PUT/GET指令的ID参数; - 地址详细信息页:TSAP自动填充为
03.00,无需修改。
关键逻辑:此ID是客户端内部连接句柄,PUT/GET指令通过它索引到正确的服务器IP和TSAP,而非直接解析IP。若后续修改ID,必须同步更新所有调用指令中的
ID值。
3.3 数据块(DB)创建与非优化访问设置:优化访问是PUT/GET失败的第一大元凶
在Client与Server两站中,分别创建以下数据块:
- DB1:用于Client发送→Server接收,数据类型为
ARRAY[0..9] OF BYTE(10字节); - DB2:用于Server发送→Client接收,数据类型同为
ARRAY[0..9] OF BYTE。
必须执行的关键操作:
- 右键DB1 → “属性” → 取消勾选“优化的块访问”(Optimized block access);
- 同样操作应用于DB2及Server侧的对应DB块。
原因说明:优化访问启用时,STEP 7会重排DB变量内存布局以提升执行效率,导致PUT/GET指令中
P#DB1.DBX0.0 BYTE 10这类绝对地址寻址失效——指令试图读取的内存地址实际存储的是其他变量。非优化访问强制保持变量按声明顺序连续排列,确保地址计算准确。
3.4 PUT/GET指令调用:OB1中的标准调用模板与参数详解
在Client站的OB1中插入PUT与GET指令(路径:Instructions → Communication → S7 Communication):
// PUT指令:将Client DB1数据发送至Server DB1 CALL "PUT", REQ := M0.0, // 上升沿触发(建议用M0.0经TON延时后触发,避免首次扫描即发) ID := W#16#100, // 必须与网络视图中连接的Local ID完全一致 DONE := M0.5, // 置位表示发送成功 ERROR := M0.6, // 置位表示故障 STATUS := MW10, // 详细状态码(如16#0000=成功,16#80B1=连接拒绝) ADDR_1 := P#DB1.DBX0.0 BYTE 10, // Server侧接收地址(DB1起始+10字节) SD_1 := P#DB1.DBX0.0 BYTE 10; // Client本地发送数据区(DB1起始+10字节) // GET指令:从Server DB2读取数据至Client DB2 CALL "GET", REQ := M1.0, // 上升沿触发(建议与PUT错开扫描周期,避免总线争用) ID := W#16#100, // 同PUT,必须一致 NDR := M1.5, // 置位表示新数据已接收 ERROR := M1.6, // 置位表示故障 STATUS := MW12, // 状态码 ADDR_1 := P#DB2.DBX0.0 BYTE 10, // Server侧发送地址(DB2起始+10字节) RD_1 := P#DB2.DBX0.0 BYTE 10; // Client本地接收数据区(DB2起始+10字节)参数逻辑说明:
REQ必须为上升沿(如M0.0经R_TRIG触发),否则指令每周期重复执行,易触发服务器限流;ADDR_1是服务器侧的数据块地址,格式P#<DB名>.DBX<字节偏移>.<位偏移> BYTE <长度>,此处DBX0.0表示DB块起始字节;SD_1(Send Data)与RD_1(Receive Data)是客户端本地数据区地址,必须与ADDR_1长度一致;DONE/NDR为单次脉冲信号,需配合SR触发器或置位复位逻辑保存状态,否则监控时一闪而过。
4. 跨项目S7通信:当两台PLC分属不同工程时,如何绕过“项目绑定”限制?
4.1 网络组态的核心差异:从“指定设备”到“未知伙伴”的范式转换
跨项目场景下,Server站不在当前项目中,因此无法在“连接对象”下拉菜单中选择。操作流程为:
- 在Client项目中,进入“网络视图” → 点击“连接”图标 → 选择“S7连接”;
- 拖拽连接线从
S7-1200_Client至空白区域(非设备图标); - 右键连接线 → “添加新连接” → 在弹窗中“连接对象”选择“未指定”(Not specified);
- 点击“确定”生成连接,此时连接列表中显示
S7_Connection_1,但远程设备栏为空。
双击该连接,在属性窗口中重点配置:
- 常规页:在“伙伴”栏选择“未知”,在“地址”栏手动输入Server的IP地址
192.168.0.12; - 地址详细信息页:必须手动设置“伙伴的TSAP”为
03.00(默认为空,若不填则通信失败); - 其他项(Local ID、主动连接)与同一项目配置一致。
关键区别:此时连接不绑定具体设备对象,而是绑定IP+TSAP组合。这意味着同一Client可同时连接多个IP不同的Server(如
192.168.0.12和192.168.0.13),只需为每个Server配置独立连接及ID。
4.2 Server端必备配置:V4.0+固件的“允许PUT/GET访问”开关
若Server为V4.0+固件(如V4.1),必须执行此步,否则Client所有PUT/GET请求均被拒绝:
- 打开Server项目 → 进入“设备视图” → 双击Server CPU图标;
- 左侧导航树选择“属性” → “常规” → “保护”;
- 在“连接机制”区域,勾选“允许从远程伙伴(PLC\HMI\OPC...)使用PUT/GET通信访问”;
- 编译并下载该配置至Server PLC。
验证方法:下载后,在Server的在线诊断中查看“保护”状态,应显示“已启用PUT/GET访问”。若未勾选,Client端STATUS恒为
16#80B1,且Server无任何日志提示。
4.3 Client端指令调用:与同一项目完全一致,但需警惕TSAP硬编码
Client端的PUT/GET调用代码与3.4节完全相同,唯一需确认的是:
ID参数仍为W#16#100(与连接属性中Local ID一致);ADDR_1地址格式不变,但需确保Server侧DB块已按3.3节要求设置为非优化访问;- 若Server侧DB块名为
DB100而非DB1,则ADDR_1必须改为P#DB100.DBX0.0 BYTE 10,否则地址越界导致STATUS=16#8105(无效地址)。
4.4 跨项目调试技巧:用Wireshark抓包定位TSAP与IP问题
当连接状态显示“未连接”或STATUS异常时,推荐用Wireshark抓取PROFINET流量:
- 在Client PC上安装Wireshark,捕获PLC网卡流量;
- 过滤条件输入
pnio或s7comm; - 触发PUT/GET指令,观察报文:
- 若看到
Cyclic Send但无Response,检查Server IP是否可达(ping 192.168.0.12); - 若看到
Request中TSAP字段为00 00(即00.00),说明Client未正确设置TSAP,需回查连接属性; - 若
Response中Return Code为05(Access denied),确认Server端保护开关已开启。
- 若看到
血泪经验:曾遇到Server IP配置为
192.168.0.12,但Client连接属性中误填为192.168.0.120,Wireshark显示Client向错误IP发包,Server毫无响应——此时ping不通,但STATUS码仍为16#8104(TSAP错误),极易误导排查方向。
5. 避坑指南:PUT/GET通信中5个高频翻车点与根因解决方案
5.1 现象:STATUS = 16#80B1(Connection refused),但网络连通性正常
原因:Server端固件为V4.0+,且未开启“允许PUT/GET访问”保护开关;或Server IP地址在Client连接属性中填写错误(如多写一位数字)。
解决:
- 检查Server设备组态→属性→保护→连接机制,确认勾选;
- 核对Client连接属性中“伙伴地址”与Server实际IP完全一致(包括子网掩码匹配);
- 若Server为V2.0,此现象几乎不可能出现,应优先排查其他原因。
5.2 现象:PUT指令DONE=1但Server DB1数据未更新;GET指令NDR=0且RD_1无数据
原因:Client或Server侧数据块未取消“优化的块访问”,导致P#DB1.DBX0.0 BYTE 10寻址到错误内存位置。
解决:
- 右键所有参与通信的DB块(Client的DB1/DB2,Server的DB1/DB2)→ “属性” → 取消勾选“优化的块访问”;
- 重新编译并下载DB块(注意:仅下载DB块即可,无需整站下载);
- 监控时观察DB块在线值,确认字节序与预期一致(如Client写
16#01020304...,Server应读到相同值)。
5.3 现象:STATUS = 16#8104(Invalid TSAP),连接状态为“未连接”
原因:跨项目通信时,Client连接属性中“伙伴的TSAP”未手动设置为03.00;或同一项目内误修改了TSAP值。
解决:
- 进入Client连接属性→“地址详细信息”页→确认“伙伴的TSAP”为
03.00; - 若为同一项目,此字段应为灰色不可编辑,若可编辑则说明连接类型错误(非S7连接);
- 重启STEP 7并重新建立连接,避免缓存导致的配置残留。
5.4 现象:GET指令NDR偶发为0,但STATUS=0,数据偶尔丢失
原因:REQ信号未做去抖动处理,导致GET指令在数据未就绪时被多次触发;或Client与Server扫描周期不匹配,Server尚未更新DB2数据。
解决:
- 将
REQ改为经TON定时器(如TON_DB.TON1(IN:=M1.0, PT:=T#100ms))输出,确保每100ms仅触发一次; - 在Server侧OB1中,于GET数据写入前添加
MOVE指令,确保DB2数据在每个扫描周期末尾更新; - 增加超时判断:若
NDR=0持续3次,置位报警位并尝试重连。
5.5 现象:Client能PUT成功但GET失败,STATUS=16#8105(Invalid address)
原因:ADDR_1(Server侧地址)与RD_1(Client侧地址)长度不一致;或Server侧DB块不存在/未下载。
解决:
- 核对
ADDR_1中BYTE 10与RD_1中BYTE 10数值完全相同; - 登录Server PLC在线,确认
DB2已下载且处于激活状态(DB块图标无红色叉号); - 检查Server DB2声明:
ARRAY[0..9] OF BYTE,而非ARRAY[1..10] OF BYTE(起始索引不同会导致地址偏移)。
6. 进阶验证与稳定性加固:用状态机+超时重试构建工业级PUT/GET通信模块
6.1 通信状态机设计:从“单次调用”到“可控会话”的跃迁
PUT/GET本质是无状态操作,但工业场景需保障数据可靠到达。我一般会封装一个状态机FB(Function Block),输入为StartTrigger,输出为DataReady与ErrorStatus,内部包含5个状态:
IDLE:等待启动信号;PUT_SEND:触发PUT,等待DONE或ERROR;PUT_CHECK:若DONE=1,跳转至GET_SEND;若ERROR=1,记录STATUS并进入RETRY;GET_SEND:触发GET,等待NDR或ERROR;RETRY:计数重试次数(上限3次),超限后置位ErrorStatus。
// FB_CommS7 状态机核心逻辑(简化版) CASE State OF 0: // IDLE IF StartTrigger THEN State := 1; PUT_REQ := FALSE; GET_REQ := FALSE; END_IF; 1: // PUT_SEND PUT_REQ := TRUE; IF PUT_DONE THEN State := 2; PUT_REQ := FALSE; ELSIF PUT_ERROR THEN RetryCount := RetryCount + 1; State := 4; END_IF; 2: // GET_SEND GET_REQ := TRUE; IF GET_NDR THEN DataReady := TRUE; State := 0; GET_REQ := FALSE; ELSIF GET_ERROR THEN RetryCount := RetryCount + 1; State := 4; END_IF; 4: // RETRY IF RetryCount >= 3 THEN ErrorStatus := PUT_STATUS; // 或 GET_STATUS State := 0; ELSE State := 1; // 重试PUT END_IF; END_CASE;6.2 超时机制实现:用TON定时器堵住“假死”漏洞
单纯依赖DONE/NDR信号存在风险:若网络瞬断,DONE可能永不置位,导致状态机卡死。因此必须加入超时:
- 在
PUT_SEND状态,启动TON_PUT定时器(PT:=T#500ms); - 若
TON_PUT.Q=TRUE且PUT_DONE=FALSE,强制置位PUT_ERROR并跳转RETRY; - 同理为
GET_SEND配置TON_GET。
参数依据:S7-1200单次PUT/GET典型耗时<100ms,设500ms超时可覆盖网络抖动,又不至于误判。
6.3 通信参数表:不同场景下的推荐配置速查
| 场景 | 推荐扫描周期 | REQ触发方式 | 超时时间 | 重试次数 | 备注 |
|---|---|---|---|---|---|
| 同一项目,调试阶段 | OB1默认 | M点上升沿 | T#200ms | 1 | 快速验证,避免干扰 |
| 跨项目,产线运行 | 100ms | TON延时后触发 | T#500ms | 3 | 平衡实时性与可靠性 |
| 高频参数同步(>10Hz) | 10ms | 硬件中断(如HSC) | T#100ms | 1 | 需确保Server能跟上节奏 |
| 低频报警上传(<1次/分) | 1000ms | 定时器+事件触发 | T#2000ms | 2 | 节省总线资源 |
6.4 最后的硬核习惯:每次下载前必做的三件事
从那以后我每次给S7-1200下载PUT/GET相关程序,都强制走一遍这三步:
- 查IP:用
ping命令确认Client与Server IP双向可达,且无丢包; - 查块:在线打开Server的DB1/DB2,确认“优化访问”已关闭,且DB块图标为绿色(已下载);
- 查保护:右键Server CPU → “在线与诊断” → “属性” → “保护”,截图保存当前设置,避免后续被他人误改。
这三步耗时不到1分钟,却能规避80%的“连不上、传不动”问题。希望帮到你。
本文还有配套的精品资源,点击获取