尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Modbus RTU与Modbus TCP核心差异:同一套问答,不同信封

发布时间:2026/9/25 10:19:13

资讯中心
01
ARTICLE

Modbus RTU与Modbus TCP核心差异:同一套问答,不同信封

Modbus RTU与Modbus TCP核心差异:同一套问答,不同信封
先聊一个我最近实际遇到的场面。车间里一台变频器和一台温控表走的是Modbus RTU挂在一条RS485总线上主站是触摸屏。现场所有调试都已经完成数据读写全部正常。结果项目收尾时上位机要数据开口就是“我们这里只支持Modbus TCP你改一下”。同事第一反应是把网线拉进去把协议整体切到TCP。我拦住他说要换的是传输的“路”不是问答的“话术”。Modbus RTU和Modbus TCP本质上用的是同一套问答规则区别只在于这句话被装进了哪一层信封。这篇文章就把这层差异彻底拆开聊清楚。先说结论Modbus RTU 和 Modbus TCP 的应用层报文——也就是功能码、数据地址、数据内容——完全一样。差别发生在数据链路层和传输层。RTU把报文当作一串字节通过RS232/RS485串行链路发送自己加从站地址和CRC校验TCP把同样的报文交给TCP/IP协议栈通过以太网发送前面多了一个MBAP头。理解了这一层你在选型、排障、写程序的时候就不会再犯“把协议不同当成寄存器不同”这种错。1. 先弄明白Modbus到底在哪个层次说话1.1 四个寄存器区和一张功能码表Modbus能成为工业现场最普及的协议不是因为它的传输方式有多先进而是因为它把数据模型定义得足够简单。它把所有设备的数据归纳成四张表线圈、离散输入、保持寄存器、输入寄存器。每一张表上都排着编号主站只需要按照功能码去读或写就行。线圈Coil可读可写的开关量用01功能码读05功能码写单个0F功能码写多个。离散输入Discrete Input只读的开关量用02功能码读。保持寄存器Holding Register可读可写的寄存器用03功能码读06功能码写单个10功能码写多个。PLC里的D区、V区一般就映射到这里。输入寄存器Input Register只读的寄存器用04功能码读常用于模拟量输入。这四张表就是Modbus的“题库”。无论底层是RS485还是以太网上位机读到的都是同一套题。这也就是“同一套问答”这句话的来历。很多人在项目里遇到“地址对不上”往往不是协议理解错了而是设备厂商把某一段数据映射到了另一张表里比如温控器的PV值在保持寄存器里而某些电能表的电压值却在输入寄存器里。1.2 一套问答哲学主站发问从站作答Modbus还有一个特点它是严格的主从问答模型。一台主站发请求从站收到后必须回复一次通讯由一问一答组成不存在从站主动上报。RTU模式下总线上只有一个主站所有从站共享同一条链路主站点名哪个站号哪个站就回答。TCP模式下通常是一个客户端向一个设备服务端发起TCP连接连接建立后在同一个连接里反复发请求。这套问答哲学意味着如果你要做的只是把一个设备里的几十个数据读上来Modbus的编程思路就是“循环发请求、收响应、解析响应”。RTU和TCP在应用层没有区别区别在发请求时要带的信封不一样。这也是为什么完全可以使用同一个寄存器地址表在RTU和TCP之间切换。1.3 为什么说“应用层完全相同”是关键这里要回到网络分层。OSI七层模型大家都不陌生Modbus协议本身只定义了应用层的内容也就是功能码加数据。在RTU里应用层报文外面要套一个串行链路层的壳从站地址、CRC校验。在TCP里应用层报文外面要套一个TCP/IP的壳MBAP头然后由TCP和IP负责可靠传输。所以题目问“差在哪一层”准确答案是差在应用层以下。RTU把帧结构全部放在串行链路层自己管TCP把传输可靠性交给TCP/IP协议栈。数据链路层和传输层不同但应用层的“问答”始终是一模一样的。这个认知极其重要因为现场排障时如果应用层数据显示不对先去查寄存器地址如果通讯完全不通再去查物理层和链路层。2. 核心差异拆解RTU和TCP的报文到底差在哪2.1 RTU的帧格式从站地址 PDU CRC16Modbus RTU的报文结构非常紧凑一帧由四部分组成。第一个字节是从站地址取值范围是1到2470x00一般作为广播地址从站收到广播地址不需要回包。第二个字节是功能码比如03就是读保持寄存器。接着是数据区长度根据功能码变化。最后是两个字节的CRC16校验低字节在前。以“读从站1的保持寄存器从地址0开始读2个寄存器”为例报文长这样01 03 00 00 00 02 [CRC_LO] [CRC_HI]这里01是站号03是功能码00 00是起始地址00 02是寄存器数量。CRC16由前面的所有字节计算得到发送时先发低字节再发高字节。RTU还有一个硬性规矩帧与帧之间要留出至少3.5个字符时间的静默间隔用来区分两帧数据。如果发送节奏被人为打乱接收方就会把前后两帧粘在一起通信直接崩溃。CRC16的算法不复杂但现场写代码时经常有人把字节序搞反。我这里贴一个标准的按位计算实现uint16_t crc16_modbus(uint8_t *buf, size_t len) { uint16_t crc 0xFFFF; for (size_t i 0; i len; i) { crc ^ buf[i]; for (int bit 0; bit 8; bit) { if (crc 0x0001) { crc (crc 1) ^ 0xA001; } else { crc 1; } } } return crc; }调用完之后把返回值拆成两个字节先发低字节。很多串口调试助手显示的是高位在前直接复制到报文里会出错。2.2 TCP的帧格式MBAP头 PDUModbus TCP在应用层报文前面加了一个7字节的MBAP头这样接收方就知道这条请求对应哪一次会话。MBAP头由四部分构成事务处理标识符、协议标识符、长度、单元标识符。事务处理标识符Transaction ID两个字节用于匹配请求和响应。同一个TCP连接上可以连续发多个请求靠这个ID对号入座。协议标识符Protocol ID两个字节Modbus协议固定为0x0000。长度Length两个字节表示后续还有多少字节也就是单元标识符加PDU的长度。单元标识符Unit ID一个字节基本就是RTU里的从站地址。同样读“从站1的保持寄存器从地址0开始读2个寄存器”Modbus TCP报文是00 01 00 00 00 06 01 03 00 00 00 02逐字节拆开是00 01是事务处理标识符00 00是协议标识符00 06表示后面还有6个字节01是单元标识符03是功能码00 00是起始地址00 02是寄存器数量。和RTU版本比一下就能看出从单元标识符开始后面的数据完全一致只是头部多了MBAP尾部少了CRC。2.3 同样的问答不同的信封逐字节对比把两个报文放在同一张表里看差异一目了然字段职责Modbus RTUModbus TCP从站/单元标识第1字节站号MBAP第7字节Unit ID功能码第2字节MBAP之后第1字节起始地址第3-4字节第3-4字节数据长度/数量第5-6字节第5-6字节完整性校验帧尾CRC16交给TCP/IP与以太网CRC这里有个很容易踩的坑很多人以为Modbus TCP把从站地址变成了IP地址其实不是。Modbus TCP里IP地址是设备在网络层的唯一身份而Unit ID依然保留着从站地址的概念。当你通过一个网关去访问网线后面的多台RTU从站设备时Unit ID就是你在TCP报文里填写的“站号”。如果直接连接一台支持Modbus TCP的设备Unit ID通常填1也有个别设备把这个字段忽略填多少都行。2.4 为什么RTU非要有CRCTCP可以不要这个问题的本质是信任边界不同。RS485串行链路没有强校验机制线上的字节可能受到电磁干扰、线路老化、接地不良的影响所以Modbus RTU必须自己计算CRC16来保证数据完整性。CRC16虽然不算特别强但足够检测出大多数突发性误码。而TCP/IP协议栈自带校验。TCP段头有16位校验和以太网帧尾部还有32位CRC双重保护之下应用层再额外加一个校验意义不大。这也是Modbus TCP报文比RTU更“干净”的原因。理解这一点对排障很有帮助RTU通讯经常遇到校验错误基本要往物理层查TCP通讯遇到数据错乱优先级更高的是检查网关配置、寄存器映射和字节序而不是怀疑线路把报文改坏了。这里还要补充一个细节Modbus TCP走的是TCP协议不是UDP。所以每次通讯要经过三次握手建立连接连接建立后长连接上反复请求响应不存在每个请求都重新握手一次的问题。三次握手解决的是“通信双方确认对方在线并同步初始序号”而真正决定报文能不能被正确解析的还是MBAP头里的事务标识符和长度字段。3. 实操同一道03号题两种写法与现场配置3.1 用调试工具发一帧完整报文我调试Modbus的习惯是先用Modbus Poll和Modbus Slave把两端的报文彻底跑通再写PLC程序。Modbus Poll是主站模拟工具Modbus Slave是从站模拟工具这两件套是我电脑上的常驻软件。用Modbus Poll测RTU时新建连接后选择Serial配置串口号、波特率、数据位、校验位和停止位。RTU最常见的串口参数是9600 8 N 1或19200 8 E 1必须和设备手册完全一致。然后填写从站地址选择功能码03填写起始地址和读取数量。点开始轮询后右侧会周期性刷新数据。用Modbus Poll测TCP时新建连接后选择TCP/IP填设备的IP地址端口默认502。下面只需要填Unit ID和功能码。TCP没有波特率校验位的概念只要IP能通、端口打开、Unit ID对应基本一次就能通。注意TCP模式下Modbus Poll的轮询时间间隔可以设得很短因为以太网不像RS485那样受半双工总线限制多寄存器并发读的效率高很多。关于Modbus Poll的注册问题我只说一句网上找的注册码大多来路不明且容易失效介意的话先用官方试用或者找正版授权别为省这点钱把工控电脑搞出安全风险。第三方的开源替代方案也有不少比如用Python的pymodbus库自己写一个测试脚本也能完成同样的工作。3.2 网关互转RS485上的RTU怎么接到TCP工业现场最常见的是把RTU总线段接进TCP网络用一台Modbus网关做桥接。网关一侧是RS485接口一侧是以太网口配置思路分三步。第一步配置串口侧参数波特率、校验位、数据位、停止位必须和总线上从站设备一致否则一个包都收不到。第二步配置从站映射表把总线上各从站的站号与TCP的Unit ID对应起来常见做法是1号从站映射到Unit ID 12号从站映射到Unit ID 2也可以把多个站映射到不同端口。第三步配置网络侧参数给网关一个固定IP开启端口502设置请求超时时间和轮询周期。我调网关时经常遇到的现象是Modbus Poll从TCP侧连网关读不到数据但用串口调试助手直接连RS485侧通得好好的。这时候十有八九是网关的串口参数或从站映射表没保存成功逐项核对一遍基本就能解决。还有一个容易忽略的坑是网关的请求超时时间设得太短RTU从站响应速度慢网关把超时当成无应答直接丢弃TCP侧自然就报超时。3.3 PLC通讯程序怎么写从站和主站的不同套路写PLC程序之前先搞清楚自己的PLC在这场问答里扮演什么角色。主站要主动发请求从站只需被问。很多初学的人拿到三菱FX3U加485BD模块做RTU从站会一直纠结“程序里要不要写轮询”。答案是不用写从站模式由通信模块自动响应你只要配置好通信格式、站号和寄存器映射主站发来请求时模块自动回包。三菱FX3U-485BD做RTU从站时要用特殊寄存器D8120设置通信格式D8121设置站号。通信格式字里每一位都对应波特率、数据位、校验位和协议类型改错一位通讯就会时通时断。调试时我最烦的就是看到D8120设置成了ASCII模式而主站发的是RTU帧两边静默通信永不响应。如果三菱PLC做主站可以用ADPRW指令。这条指令本质上是封装了“发送请求、等待响应、存回数据”的完整流程。用的时候要填清模块号和发送数据内容比如发一条03读保持寄存器的请求需要在数据区里依次填写功能码、起始地址、读取数量和校验结果存储位置。ADPRW指令适合单条轮询数据多了以后我更推荐用以太网口的TCP功能三菱FX5U或Q系列可以直接用内置以太网口做Modbus TCP主站或从站配置界面比串口指令直观得多。西门子这边常见的组合是S7-1200加CM1241 RS485模块去和变频器做Modbus通讯。CM1241本身不支持Modbus TCP只负责RS485物理层需要在TIA Portal里调用Modbus通信指令。具体指令包括初始化通信口的MB_COMM_LOAD和发送请求的MB_MASTER。用MB_MASTER时要注意“数据指针”和“长度”要一一对应不然读回来的数据错位非常难查。汇川PLC的寄存器地址规则和三菱类似D区映射到保持寄存器输入点映射到输入寄存器。做RTU通讯时H系列通过H5U等自带串口的型号可以直接配置Modbus主从站或者用外部485模块。寄存器地址经常出现协议内偏移和HMI显示偏移不一致的问题最简单的处理方式是抓包确认实际报文的起始地址到底是多少不要凭记忆拍脑袋。4. 常见问题与排查技巧实录4.1 排查思路先分方向再分层次遇到Modbus通讯不通我的第一反应不是翻手册而是先判断问题大概出在哪个方向。RTU不通先确认串口链路是否物理连通再确认链路参数是否一致。TCP不通先ping设备IP确认网络通不通再确认端口502是否可达最后才查Modbus层报文内容。这个顺序一错很容易在错误的层次里白折腾几个小时。有一类特别典型的问题Modbus Poll已经收到了数据但数据明显不对比如读出来的数值全是最大值或者全是零。这种情况不要第一个怀疑协议先检查寄存器映射是否正确地址有没有偏移。再检查字节序很多温控表、电表都是大端存储PLC里默认小端处理高低字节一颠倒读出来就是天文数字。4.2 RTU现场高频问题速查表故障现象常见原因处理方式一个从站都不响应RS485 A/B接反对调A/B线看回包某个站时通时断链路里有站号重复逐一检查从站拨码CRC校验错误频繁波特率或校验位不一致统一总线参数总线一挂多台就乱缺少终端电阻总线两端各并120Ω偶发丢包线缆过长或绕高干扰源换屏蔽双绞线做好接地分离这里特别说一下终端电阻。RS485总线要求在物理最远两端各接一个120欧姆电阻终端电阻不是可有可无的东西距离短、设备少时还能跑距离一长立刻出现信号反射现象就是同一个站多读几次才成功一次甚至偶尔读到乱码。现场调试时我一般先在总线上只留一台从站测试通了再加第二台这样可以快速排除信号反射和地址冲突的问题。4.3 TCP现场高频问题速查表故障现象常见原因处理方式网络通但502连不上设备端口被防火墙拦截放行502或临时关防火墙验证连上但一直超时Unit ID或寄存器地址错误用Modbus Poll抓实际请求请求和响应错配Transaction ID不唯一检查主站是否重用ID多主站轮询时互踢两个客户端同时写冲突只允许一个主站写其余只读数据刷新缓慢网关轮询周期太长缩短网关请求间隔TCP排障最犀利的工具是Wireshark。过滤器直接写tcp.port 502就能看到Modbus TCP的完整请求响应。看报文时重点看三样事务处理标识符是不是一一对应、MBAP长度字段对不对、功能码和寄存器地址是否和配置一致。如果抓包看到请求发出去了但设备没回那就是设备侧没有正确解析如果根本没抓到请求问题在上位机或网卡。4.4 抓包与串口监视三个让我少踩坑的工具细节第一个细节是Wireshark的TCP校验和误报。因为网卡普遍开启硬件校验卸载Wireshark抓到的报文里TCP checksum可能是错误的显示成红色。这不一定代表真错误需要关掉或忽略否则会误导排查方向。第二个细节是串口监视工具调试RTU时不要只看设备侧数据最好用一个虚拟串口或带监听功能的总线分析仪把实际线上的字节流完整录下来。这样能看到帧间隔是否正确、CRC是否合格、是不是有设备抢占总线。第三个细节是Modbus Poll的响应超时设置。RTU模式默认超时时间可能只有几十毫秒如果你的从站需要做EEPROM写入或者本身处理慢要先把超时调大再排查其他问题。很多“时通时断”其实是超时阈值卡得太死而不是线路有干扰。把这个超时参数调宽之后大量假故障都会消失。我个人的体会是把Modbus当成一套固定题库把RTU和TCP当成两种不同的送卷方式现场很多问题都会瞬间变清晰。调试的时候不要急着用PLC程序背锅先用Modbus Poll把主站侧的报文发通了再用Modbus Slave模拟从站把响应校验对了最后再接真实设备。如果你手头有RTU转TCP的网关记得先分别验证串口段和网络段再合起来联调。这也是我每次做跨协议项目都反复用的方法省下的时间远比想象的多。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。