4、Modbus通信原理:主从架构、请求响应机制、地址映射、字节序与数据类型(16位、32位、浮点、字符串)
Modbus协议诞生于1979年,由Modicon(现施耐德电气)公司开发,至今仍是工业自动化领域应用最广泛的通信协议之一。在ThingsBoard物联网平台中,通过Modbus网关或直接集成Modbus设备,可以快速将PLC、电表、温控器、变频器等工业设备接入云端。理解Modbus通信原理,是完成设备接入、数据解析和故障排查的基础。本章将围绕主从架构、请求响应机制、地址映射、字节序与数据类型四个核心维度展开,并结合ThingsBoard中的实际配置场景进行讲解。
4.1 主从架构:谁发起,谁响应
Modbus协议采用严格的主从(Master/Slave)通信模型。在同一个Modbus网络中,只允许存在一个主站(Master),而从站(Slave)可以有多个,典型数量为1到247个。主站负责发起所有通信请求,从站只能被动响应,不能主动向主站发送数据。这种架构设计保证了通信的确定性,避免了总线冲突,非常适合工业现场对实时性和可靠性要求较高的场景。
在ThingsBoard的Modbus集成中,ThingsBoard网关或Modbus Connector扮演主站角色,而PLC、传感器、电表等设备作为从站。主站按照配置的轮询周期,周期性地向各个从站发送读取请求,获取设备数据;也可以发送写入请求,实现对设备的远程控制。主从架构的核心规则包括:
- 唯一主站:一个Modbus网络中只能有一个主站,否则会导致总线冲突和数据混乱。
- 从站地址唯一:每个从站必须拥有唯一的地址(1-247),主站通过地址来区分不同的设备。
- 从站不能主动通信:从站只能在收到主站请求后,才能回复数据或执行操作。
- 通信时序:主站发送请求后,必须等待从站响应或超时,才能发起下一次请求。
4.2 请求响应机制:功能码与事务处理
Modbus通信的核心是请求-响应机制。主站发送一个请求帧,从站处理并返回一个响应帧。请求帧和响应帧的结构因传输模式(RTU、ASCII、TCP)而异,但都包含关键字段:从站地址、功能码、数据区和校验码。功能码决定了操作类型,常见功能码如下表所示:
| 功能码 | 操作类型 | 寄存器区域 | 读写方向 | 典型应用 |
|---|---|---|---|---|
| 01 (0x01) | 读线圈状态 | 线圈 (Coil) | 只读 | 读取开关量输出状态 |
| 02 (0x02) | 读离散输入状态 | 离散输入 (Discrete Input) | 只读 | 读取按钮、限位开关状态 |
| 03 (0x03) | 读保持寄存器 | 保持寄存器 (Holding Register) | 读写 | 读取/写入模拟量、参数配置 |
| 04 (0x04) | 读输入寄存器 | 输入寄存器 (Input Register) | 只读 | 读取传感器测量值 |
| 05 (0x05) | 写单个线圈 | 线圈 | 只写 | 控制单个开关量输出 |
| 06 (0x06) | 写单个保持寄存器 | 保持寄存器 | 只写 | 修改单个参数 |
| 15 (0x0F) | 写多个线圈 | 线圈 | 只写 | 批量控制开关量输出 |
| 16 (0x10) | 写多个保持寄存器 | 保持寄存器 | 只写 | 批量修改参数 |
在ThingsBoard的Modbus Connector中,配置读取请求时,需要指定功能码、起始地址和寄存器数量。例如,要读取一个电表的电压值(存储在输入寄存器地址0x0000,占用2个寄存器),可以配置功能码04,起始地址0,寄存器数量2。ThingsBoard会按照此配置周期性地发送读取请求,并将响应数据解析为设备属性或遥测数据。
请求帧: 01 03 00 00 00 02 C4 0B
- 01: 从站地址
- 03: 功能码(读保持寄存器)
- 00 00: 起始地址(高字节在前)
- 00 02: 寄存器数量
- C4 0B: CRC16校验码
响应帧: 01 03 04 00 0A 00 14 7A 9E
- 01: 从站地址
- 03: 功能码
- 04: 数据字节数(2个寄存器 × 2字节 = 4字节)
- 00 0A: 寄存器0的值(十进制10)
- 00 14: 寄存器1的值(十进制20)
- 7A 9E: CRC16校验码
如果从站检测到请求中的错误(如非法功能码、非法数据地址、非法数据值),会返回异常响应帧。异常响应帧的功能码最高位置1(即原功能码+0x80),并附带一个异常码。常见的异常码包括:01(非法功能)、02(非法数据地址)、03(非法数据值)、04(从站设备故障)。在ThingsBoard的日志中,如果看到类似"Modbus exception response: code 02"的信息,说明请求的寄存器地址超出了从站的有效范围。
4.3 地址映射:从Modbus地址到ThingsBoard属性
Modbus协议中的地址映射是设备接入的核心环节。Modbus地址空间分为四个区域,每个区域有独立的地址范围和数据特性。理解这些地址区域,有助于正确配置ThingsBoard中的地址映射关系。
| 区域名称 | 地址范围(PLC习惯) | Modbus协议地址 | 数据类型 | 读写属性 |
|---|---|---|---|---|
| 线圈 (Coil) | 00001 - 09999 | 0x0000 - 0xFFFF | 位 (Bit) | 读写 |
| 离散输入 (Discrete Input) | 10001 - 19999 | 0x0000 - 0xFFFF | 位 (Bit) | 只读 |
| 输入寄存器 (Input Register) | 30001 - 39999 | 0x0000 - 0xFFFF | 16位字 | 只读 |
| 保持寄存器 (Holding Register) | 40001 - 49999 | 0x0000 - 0xFFFF | 16位字 | 读写 |
在ThingsBoard的Modbus Connector配置中,地址映射通常包含以下关键字段:寄存器类型(Coil、Discrete Input、Input Register、Holding Register)、寄存器地址(从0开始的偏移地址)、数据类型(16位整数、32位整数、浮点数、字符串等)、字节序和字序。例如,一个温湿度传感器将温度值存储在保持寄存器地址0x0000(32位浮点数),湿度值存储在地址0x0002(32位浮点数),则配置如下:
{
"registerType": "HOLDING_REGISTER",
"address": 0,
"dataType": "FLOAT",
"byteOrder": "BIG_ENDIAN",
"wordOrder": "WORD_ORDER_BIG_ENDIAN",
"multiplier": 0.1,
"attributeName": "temperature"
}
这里的multiplier字段用于数据缩放,例如设备原始值为250,乘以0.1后得到25.0°C。在配置地址映射时,需要注意以下几点:
- 地址偏移:Modbus协议中的地址从0开始,而PLC习惯的地址从1开始。例如PLC中的40001对应Modbus协议地址0x0000。
- 寄存器数量:32位数据类型占用2个连续寄存器,字符串类型根据长度占用多个寄存器。
- 数据类型匹配:确保配置的数据类型与设备实际存储的数据类型一致,否则解析结果将出现错误。
4.4 字节序与数据类型:解析数据的核心
Modbus协议中,16位数据(1个寄存器)的字节序相对简单,但32位数据(2个寄存器)和浮点数的字节序与字序组合复杂,是数据解析中最容易出错的部分。字节序(Byte Order)指的是在一个寄存器内部,高字节和低字节的排列顺序;字序(Word Order)指的是在多个寄存器之间,高字和低字的排列顺序。
4.4.1 16位整数
16位整数占用1个寄存器(2字节),在Modbus RTU和TCP中,默认采用大端字节序(Big-Endian),即高字节在前,低字节在后。例如,寄存器值0x1234,在总线上的传输顺序为0x12、0x34。在ThingsBoard中,16位整数的字节序通常不需要额外配置,默认即为大端。
4.4.2 32位整数与浮点数
32位数据(包括32位整数和IEEE 754浮点数)占用2个连续寄存器。字节序和字序的组合共有四种常见模式:
| 模式名称 | 字节序 | 字序 | 示例(寄存器0=0x1234, 寄存器1=0x5678) | 解析结果 |
|---|---|---|---|---|
| Big-Endian / Big Word | 高字节在前 | 高字在前 | 12 34 56 78 | 0x12345678 |
| Big-Endian / Little Word | 高字节在前 | 低字在前 | 56 78 12 34 | 0x56781234 |
| Little-Endian / Big Word | 低字节在前 | 高字在前 | 34 12 78 56 | 0x34127856 |
| Little-Endian / Little Word | 低字节在前 | 低字在前 | 78 56 34 12 | 0x78563412 |
在ThingsBoard的Modbus Connector中,可以通过byteOrder和wordOrder字段来配置字节序和字序。例如,对于常见的施耐德电气设备,通常使用Big-Endian / Big Word模式;而对于西门子S7-200系列PLC,可能使用Big-Endian / Little Word模式。浮点数的解析遵循IEEE 754标准,例如32位浮点数0x3F800000表示1.0,0x40000000表示2.0。
假设设备返回两个寄存器值:寄存器0 = 0x4048, 寄存器1 = 0xF5C3
采用 Big-Endian / Big Word 模式:
组合字节序列: 40 48 F5 C3
按照IEEE 754解析:
- 符号位: 0 (正数)
- 指数位: 10000000 (二进制) = 128, 减去127 = 1
- 尾数位: 10010001111010111000011 (二进制)
- 数值 = 1.10010001111010111000011 × 2^1 ≈ 3.14
因此,该浮点数表示约3.14。
4.4.3 字符串类型
Modbus中的字符串通常以ASCII码形式存储在多个连续的保持寄存器或输入寄存器中。每个寄存器可以存储2个ASCII字符(高字节和低字节各一个)。字符串的字节序同样需要关注,常见的有两种模式:
- 高字节在前:第一个字符存储在寄存器的高字节,第二个字符存储在低字节。
- 低字节在前:第一个字符存储在寄存器的低字节,第二个字符存储在高字节。
在ThingsBoard中配置字符串类型时,需要指定字符串长度(以字符数计)和字节序。例如,一个设备返回设备序列号,存储在保持寄存器地址0x0010开始,共4个寄存器(8个字符),采用高字节在前模式,配置如下:
{
"registerType": "HOLDING_REGISTER",
"address": 16,
"dataType": "STRING",
"stringLength": 8,
"byteOrder": "BIG_ENDIAN",
"attributeName": "serialNumber"
}
解析时,ThingsBoard会将4个寄存器的8个字节按顺序拼接,然后转换为ASCII字符串。如果设备返回的字符串包含非ASCII字符或使用了UTF-8编码,则需要额外处理。
4.5 实战案例:电表数据接入ThingsBoard
下面通过一个完整的案例,演示如何将一台Modbus RTU电表接入ThingsBoard,并正确解析电压、电流和功率数据。
设备信息:某型号三相电表,使用Modbus RTU协议,从站地址为1,波特率9600,数据位8,停止位1,无校验。电表寄存器定义如下:
| 参数名称 | 寄存器地址 | 数据类型 | 字节序/字序 | 缩放系数 |
|---|---|---|---|---|
| A相电压 | 0x0000 | 32位浮点 | Big-Endian / Big Word | 1.0 |
| B相电压 | 0x0002 | 32位浮点 | Big-Endian / Big Word | 1.0 |
| C相电压 | 0x0004 | 32位浮点 | Big-Endian / Big Word | 1.0 |
| 总功率 | 0x0006 | 32位浮点 | Big-Endian / Big Word | 1.0 |
| 累计电量 | 0x0008 | 32位整数 | Big-Endian / Big Word | 0.001 |
配置步骤:
- 在ThingsBoard中安装并配置Modbus Connector,设置连接参数(串口、波特率等)。
- 创建设备,配置从站地址为1。
- 添加地址映射,按照上表配置5个参数的寄存器地址、数据类型和字节序。
- 设置轮询周期为5秒,保存配置并启动连接。
验证与排障:启动后,在ThingsBoard的设备遥测页面查看数据。如果电压值显示异常(如负数或极大值),首先检查字节序和字序配置是否正确。可以使用Modbus Poll工具读取相同地址的数据,对比解析结果。如果Modbus Poll显示正常而ThingsBoard异常,则检查ThingsBoard中的数据类型和缩放系数配置。
复盘总结:本案例中,电表数据接入的关键在于正确理解寄存器地址映射和字节序配置。通过先使用调试工具验证,再配置到ThingsBoard,可以有效减少排障时间。在实际项目中,建议建立设备寄存器映射文档,记录每个参数的地址、数据类型、字节序和缩放系数,便于后续维护和扩展。
4.6 常见误区与总结
在Modbus设备接入ThingsBoard的过程中,以下误区需要特别注意:
- 误区一:忽略从站地址。多个设备共用总线时,地址冲突会导致通信失败。配置前应检查所有设备的地址设置。
- 误区二:寄存器地址混淆。PLC习惯地址(如40001)与Modbus协议地址(0x0000)的转换错误,会导致读取到错误的数据。
- 误区三:字节序配置错误。不同厂商的设备可能采用不同的字节序和字序,必须查阅设备手册确认。
- 误区四:忽略超时和重试设置。在RS-485总线上,如果从站响应较慢,需要适当增加超时时间,否则会导致通信失败。
- 误区五:数据类型不匹配。将32位浮点数配置为16位整数,或反之,会导致数据解析错误。
本章系统讲解了Modbus通信原理的四个核心维度:主从架构、请求响应机制、地址映射、字节序与数据类型。掌握这些知识,是使用ThingsBoard进行Modbus设备接入的基础。在实际项目中,建议结合Modbus调试工具(如Modbus Poll、Modbus Slave)进行验证,确保配置正确后再部署到生产环境。