Modbus是一种工业设备之间交换数据的应用层通信协议。发起端用功能码说明“做什么”,用地址说明“访问哪里”,接收端再返回数据或执行结果。PLC读取仪表测量值、上位机读取设备状态,都可以采用这种请求—响应方式。
Modbus RTU和Modbus TCP共享基本的数据模型与功能码,主要区别在通信承载和报文外层格式。RTU常用于RS-485串行链路,TCP运行在TCP/IP之上。理解Modbus,要同时看懂设备如何被找到、数据如何被寻址,以及返回的字节如何变成有意义的数值。

Modbus传输的是什么,谁发起通信
设想上位机要读取一台仪表的温度:上位机先发出读取请求,仪表查找对应数据并返回,上位机再根据仪表数据表解释数值。这一来一回构成一次事务。设备会不会主动推送、何时刷新测量值、单位是什么,并不能仅从“支持Modbus”推断出来。
在应用层,发起请求的一方称为客户端,响应的一方称为服务器;串行规范和不少设备手册沿用主站、从站的称呼。Modbus串行规范采用单主站组织通信,同一时刻由主站发起一个事务,多个从站按地址区分。PLC并不天然只能做主站或从站,它在具体连接中扮演什么角色,要看实现和配置。
通信协议也不等于物理接口。RS-485规定电气层面的传输方式,并不规定“读哪个寄存器”;Modbus规定的数据访问也不只存在于RS-485上。把这一层次放回现场总线与工业通信的框架,才能避免看到网口就认定是Modbus TCP,或者看到两根通信线就认定是Modbus RTU。
四类数据区与常用功能码
Modbus将可访问的数据组织为四类逻辑对象:两类每项占1位,表达开或关;两类每项占16位,可承载数值或位组合。下表的“只读”和“读写”是从远程客户端访问的角度而言,本地设备仍可更新测量值和输入状态。它们是逻辑数据区,不要求硬件里恰好存在四块独立存储器。
| 数据区 | 每项大小 | 远程访问 | 读取功能码 | 理解方式 |
|---|---|---|---|---|
| 线圈(Coils) | 1 bit | 读/写 | 0x01 | 可读写的开关量;不一定对应实体继电器 |
| 离散量输入(Discrete Inputs) | 1 bit | 只读 | 0x02 | 设备开放的二值输入或状态 |
| 保持寄存器(Holding Registers) | 16 bit | 读/写 | 0x03 | 参数、过程值或组合数据,具体权限由设备规定 |
| 输入寄存器(Input Registers) | 16 bit | 只读 | 0x04 | 设备开放的测量值或状态字 |
功能码将对象与操作一起确定。读保持寄存器用0x03,读输入寄存器用0x04;即使起始地址相同,也不应互换。写单个线圈用0x05,写单个保持寄存器用0x06;写多个线圈和多个保持寄存器分别用0x0F、0x10。这里采用十六进制表示,0x10等于十进制16,不是十进制10。Modbus应用协议规范分别定义了这些请求与响应格式。
“保持寄存器”这个名称不承诺断电后保存。某个参数能不能写、写后是否需要保存命令、设备是否支持整个地址范围,都属于设备的数据映射和实现。协议给出了访问方式,并不要求每台设备实现全部功能码和全部寄存器。

Modbus RTU和TCP:相同PDU,不同外层格式
理解两者的共同点,可以先抓住PDU(协议数据单元):它由功能码及对应数据组成。例如读取寄存器时,数据部分包含起始地址和数量。把PDU装入适合某种传输方式的外层格式后,形成ADU(应用数据单元)。RTU和TCP正是在这层封装上有明显差别。
| 比较项 | Modbus RTU | Modbus TCP |
|---|---|---|
| 常见承载 | 串行线路,工业现场常见RS-485 | TCP/IP,常见于以太网 |
| 应用报文结构 | 1字节设备地址+PDU+2字节CRC | 7字节MBAP头+PDU |
| 设备与事务识别 | 串行设备地址;主站组织请求与响应 | IP和端口定位服务器;事务标识匹配响应,Unit ID可参与网关路由 |
| 报文边界 | 依据串行时序与帧间静默规则 | 依据MBAP长度字段解析TCP字节流 |
| 相关通信参数 | 波特率、数据格式、校验设置、地址等 | IP、端口、连接和超时设置等;普通Modbus TCP常用端口502 |
同一串行链路各设备的波特率与字符格式,包括数据位、校验和停止位,须相互一致。RTU接收端还需要知道一串字节何时结束,因此帧间静默是协议的一部分。串行规范在不高于19200 bit/s时规定至少3.5个字符时间的帧间间隔;更高波特率推荐固定1.75 ms的帧间间隔。这里的“字符时间”包含一次串行字符传输所需的位时间,不是只计算8个数据位。CRC用于发现帧传输中的差错,它不是加密。
TCP的MBAP头包含2字节事务标识、2字节协议标识、2字节长度和1字节Unit ID。Beckhoff的Modbus TCP字段表列明了这七个字节的位置;普通Modbus的协议标识为0,长度字段统计其后的Unit ID与PDU字节。事务标识帮助客户端把响应对应到请求。TCP是字节流,一次底层接收调用不保证恰好拿到一个完整Modbus报文,应用程序仍要按长度正确组帧。
标准Modbus TCP报文不附加RTU的CRC,但TCP及下层网络有自己的差错检测与传输机制,不能据此说TCP“没有校验”。这些机制也不等于身份认证、加密或确定的最坏响应时间。

在TCP转RTU网关后面挂多台仪表时,客户端先连接网关的IP和端口,网关可用Unit ID确定后面的目标串行设备,再转换报文封装。NI的协议说明解释了这一网关用途。直接连接TCP设备时Unit ID如何处理,应看设备要求,不能一概设成0。只把完整RTU字节通过TCP连接透传的“RTU over TCP”,也不等同于带MBAP头的标准Modbus TCP;两端封装必须一致。
40001为什么可能对应地址0
“地址”至少要分成两件事:先找到哪一台设备,再找到该设备的哪一项数据。串行设备地址7不是寄存器地址7;TCP的IP地址也不是寄存器地址。进入设备后,还需要通过功能码确定数据区,再通过PDU中的起始地址定位数据项。
Modbus PDU中的数据地址从0开始,而设备手册常用带数据区前缀的引用编号。假设某份手册明确以40001表示第一个保持寄存器、40002表示第二个,那么读取第一项时,线上的请求应使用功能码0x03、起始地址0;读取第二项则使用起始地址1。40001中的前缀4帮助人识别保持寄存器区,不是把十进制40001原样塞进这个例子的起始地址字段。

容易出错的地方在软件输入框。有的驱动要求填原始偏移0,有的要求填寄存器序号1,有的直接接受40001并代为转换。手册本身也可能使用不同长度的编号或从0开始编号。正确做法是先确认设备表的编号规则,再确认客户端输入规则,最后核对实际发送的功能码和起始地址;不能对所有软件统一“减1”或“减40001”。
一次读寄存器请求怎样变成两个数值
继续采用上述假设:第一个保持寄存器对应PDU地址0,现在连续读取两个。以下只展示PDU,所有报文字节均以十六进制写出,未包含RTU设备地址、CRC或TCP的MBAP头:
请求:03 00 00 00 02
第一个字节03表示读保持寄存器;接下来的00 00是起始地址0;最后的00 02是数量2。设备正常返回时,假设两个寄存器的原始值分别为十进制100和200,响应为:
响应:03 04 00 64 00 C8
03回应原功能码;04表示后面有4个数据字节,而不是4个寄存器。00 64组成第一个16位值,即0x0064=100;00 C8组成第二个,即0x00C8=200。两个寄存器,每个2字节,正好共4字节。功能0x03一次请求的规范数量范围为1至125个寄存器,但实际设备可支持更小范围;连续读取也必须落在设备已实现的地址区间内。

得到100还不意味着得到100℃。如果示例设备表规定第一项是无符号整数、每单位代表0.1℃,则100才应解释为10.0℃;若它实际是状态字,100的各个位可能代表不同状态。这个换算系数是本例假设,不是Modbus规定。
单个16位寄存器在线上传输时高字节在前,所以0x0064发送为00 64。但32位整数或浮点数通常跨两个寄存器,哪个寄存器先放高16位、数据是否有符号、是否需要比例或偏移,都要依据设备数据表。不能只看到两个寄存器就默认是一个浮点数,也不能把单寄存器的大端规则当成跨寄存器字序的统一规定。
写入的响应格式则不同。另设一个纯教学条件:设备在PDU地址2开放一个可写的16位测试参数,拟写入原始值123。功能0x06的请求为06 00 02 00 7B:06是写单个寄存器,00 02是地址2,00 7B是数值123。按应用协议规范,正常响应回显相同PDU,确认该写入已完成,而不是像读取响应那样带数据字节数。至于参数何时影响设备动作、是否断电保存,仍须看该参数定义;这组教学字节不能直接用于未知设备。
通信异常、超时与数值不对,各说明什么
调试时先把三种情况分开,后续检查才有方向。
- 完全收不到有效响应:先检查请求是否到达目标。RTU侧关注地址、串行参数和线路,TCP侧关注IP、端口、连接及网关路由;再判断设备处理时间是否超出设置。超时本身不能证明一定是接线错。
- 收到Modbus异常响应:说明对端返回了可解析的协议级错误。异常功能码会把原功能码的最高位置1,例如0x03对应0x83。PDU
83 02表示读保持寄存器请求遇到非法数据地址,应检查数据区、起始地址以及“起始地址+读取数量”是否越界,而不是只检查第一个地址。 - 收到正常响应,数值却不对:先确认读到的是正确的数据区和偏移,再核对字节/字序、类型、比例、单位和刷新条件。有效响应只证明这次访问有结果,不证明取到的就是所需测点,也不证明值一定刚刚更新。
Modbus适合把设备开放的状态、测量量和参数交给其他系统读取或写入;真正的互通仍依赖双方对数据表的共同理解。写入参数前还要确认该地址的实际含义与生效方式,不能把“功能码支持写入”当成任意地址都可修改。
普通Modbus TCP也不默认提供通信身份认证和加密。Modbus组织另外定义了采用TLS与X.509证书的Modbus Security。这是需要双方支持并配置的另一种安全机制,不能因为设备接入TCP/IP网络,就认为它已自动具备这些保护。
参考资料
- Modbus Organization:应用协议规范V1.1b3,数据模型、地址、功能0x03和异常响应。
- Modbus Organization:串行线路规范与实施指南V1.02,串行事务与RTU分帧。
- Beckhoff:ModbusTCP Protocol,TCP端口与MBAP字段。
- NI:深入解读Modbus协议,引用编号、数据解释与网关封装。
- Modbus Organization:规范入口,各规范与Modbus Security的关系。
评论留言
暂时没有留言!