Modbus RTU 协议介绍

Modbus RTU 协议介绍

异步串行传输方式,采用二进制格式,适用于串行通讯(如RS-485),效率高,是工业现场的主流选择。

主站是Master,从站是Slave。

Modbus RTU 协议格式

帧结构

  • 地址码(1字节):从设备的地址,取值1-247。
  • 功能码(1字节):指定操作类型,如读取或写入。
  • 数据区(长度可变):包含具体的操作数据。
  • CRC校验(2字节):循环冗余校验码,确保数据无误。

功能码

功能码功能用途
01读线圈状态获取开关量输出状态
03读保持寄存器获取16位可读写数据
04读输入寄存器获取16位只读数据
05写单个线圈控制单个开关量输出
06写单个寄存器修改单个16位数据
16(0x10 十六进制)写多个寄存器修改多个16位数据

CRC 校验

CRC(循环冗余校验)是Modbus RTU的关键,用于检测传输错误。发送方计算CRC并附加在帧尾,接收方重新计算并比对。

CRC16校验算法示例:

const unsigned short wCRCTalbeAbs[] =
{
    0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401, 0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400,
};

unsigned short mt_api_crc16(unsigned char *ptr, unsigned int len) 
{
    unsigned short wCRC = 0xFFFF;
    unsigned short i;
    unsigned char chChar;
    unsigned char temp[2];
    for (i = 0; i < len; i++)
    {
        chChar = *ptr++;
        wCRC = wCRCTalbeAbs[(chChar ^ wCRC) & 15] ^ (wCRC >> 4);
        wCRC = wCRCTalbeAbs[((chChar >> 4) ^ wCRC) & 15] ^ (wCRC >> 4);
    }
    temp[0] = wCRC&0xFF; 
    temp[1] = (wCRC>>8)&0xFF;
    wCRC = (temp[0]<<8)|temp[1];
    return wCRC;
}

0x01 功能码(读线圈状态)

请求数据

01 01 00 00 00 08 9C 03
  • 01:从设备地址(1-247)
  • 01:功能码(读线圈状态)
  • 00 00:起始线圈地址(2 字节)
  • 00 08:线圈个数(读取 8 个线圈)
  • 9C 03:CRC校验

更详细的格式如下:

从设备地址 + 功能码 + 起始线圈地址(高位) + 起始线圈地址(低位) + 线圈数量(高位) + 线圈数量(低位) + CRC(高位) + CRC(低位),一共 8 个字节。

响应数据

01 01 01 55 78 3A
  • 01:从设备地址(1-247)
  • 01:功能码(读线圈状态)
  • 01:线圈状态数据的总字节数(<font style="color:rgb(0, 0, 0);">ceil(线圈数量/8)</font>,8 个线圈 = 1 字节)
  • 55:线圈状态数据(1 个字节)
  • 78 3A:CRC 校验

更详细的格式如下:

从设备地址 + 功能码 + 数据长度 + [线圈状态数据(N 字节)] + CRC(高位) + CRC(低位)

0x03 功能码(读保持寄存器)

请求数据

01 03 00 00 00 01 C4 0B
  • 01:从设备地址(1-247)
  • 03:功能码(读保持寄存器)
  • 00 00:起始寄存器地址(2 字节)
  • 00 01:寄存器个数(读取 1 个寄存器)
  • C4 0B:CRC校验

更详细的格式如下:

从设备地址 + 功能码 + 起始寄存器地址(高位) + 起始寄存器地址(低位) + 寄存器数量(高位) + 寄存器数量(低位) + CRC(高位) + CRC(低位),一共 8 个字节。

响应数据

01 03 02 19 98 B2 7E
  • 01:从设备地址(1-247)
  • 03:功能码(读保持寄存器)
  • 02:后面数据的字节数,一个寄存器有 2 个字节,所以后面的字节数等于 2*查询的寄存器数量
  • 19 98:寄存器的值是 19 98
  • B2 7E:CRC 校验

更详细的格式如下:

从设备地址 + 功能码 + 数据长度 + 寄存器数据 + CRC 校验码

字节数:1+1+1+2*N+2

0x04 功能码(读输入寄存器)

请求数据

01 04 00 01 00 03 60 0A 
  • 01:从设备地址(1-247)
  • 04:功能码(写输入寄存器)
  • 00 01:起始寄存器地址(2 字节)
  • 00 03:输入寄存器数量
  • 60 0A:CRC 校验

更详细的格式如下:

从设备地址 + 功能码 + 起始寄存器地址(高位) + 起始寄存器地址(低位) +寄存器数量(高位) + 寄存器数量(低位) + CRC 校验(高位) + CRC 校验(高位),一共 8 个字节。

响应数据

01 04 06 00 0A 01 F4 03 E8 75 3B
  • 01:从设备地址(1-247)
  • 04:功能码(写输入寄存器)
  • 06:输入寄存器数据的总字节数(寄存器数量 ×2,3×2=6 字节)
  • 00 0A:第一个输入寄存器值
  • 01 F4:第二个输入寄存器值
  • 03 E8:第三个输入寄存器值
  • 75 3B:CRC 校验

更详细的格式如下:

从设备地址 + 功能码 + 数据长度 + [N 组寄存器数据(每组 2 字节)] + CRC 校验(高位) + CRC 校验(高位)

0x05 功能码(写单个线圈)

请求数据

01 05 00 03 FF 00 8C 3A
  • 01:从设备地址(1-247)
  • 05:功能码(写单个线圈)
  • 00 03:目标线圈地址
  • FF 00:线圈状态值
  • 8C 3A:CRC 校验

更详细的格式如下:

从设备地址 + 功能码 + 目标线圈地址(高位) + 目标线圈地址(低位) + 线圈状态值(高位) + 线圈状态值(低位) + CRC 校验(高位) + CRC 校验(高位),一共 8 个字节。

响应数据

01 05 00 03 FF 00 8C 3A
  • 01:从设备地址(1-247)
  • 05:功能码(写单个线圈)
  • 00 03:目标线圈地址
  • FF 00:线圈状态值
  • 8C 3A:CRC 校验

更详细的格式如下:

从设备地址 + 功能码 + 目标线圈地址(高位) + 目标线圈地址(低位) + 线圈状态值(高位) + 线圈状态值(低位) + CRC 校验(高位) + CRC 校验(高位),一共 8 个字节。

0x06 功能码( 写单个保持寄存器)

请求数据

01 06 00 00 00 01 48 0A
  • 01:从设备地址(1-247)
  • 06:功能码(写保持寄存器)
  • 00 00:起始寄存器地址(2 字节)
  • 00 01:写入的值
  • 48 0A:CRC校验

更详细的格式如下:

从设备地址 + 功能码 + 起始寄存器地址(高位) + 起始寄存器地址(低位) + 写入值(高位) + 写入值(低位) + CRC(高位) + CRC(低位),一共 8 个字节。

响应数据

01 06 00 00 00 01 48 0A
  • 01:从设备地址(1-247)
  • 06:功能码(写保持寄存器)
  • 00 00:起始寄存器地址(2 字节)
  • 00 01:写入的值
  • 48 0A:CRC校验

更详细的格式如下:

从设备地址 + 功能码 + 起始寄存器地址(高位) + 起始寄存器地址(低位) + 写入值(高位) + 写入值(低位) + CRC(高位) + CRC(低位),一共 8 个字节。

0x010 功能码( 写多个保持寄存器)

请求数据

01 10 00 02 00 03 06 00 0A 01 02 03 04 75 F5
  • 01:从设备地址(1-247)
  • 10:功能码(写保持寄存器)
  • 00 02:起始寄存器地址(2 字节)
  • 00 03:寄存器数量
  • 06:后续数据的总字节数(寄存器数量 x 2)
  • 00 0A:写入数据 1(2 字节)
  • 01 02:写入数据 3(2 字节)
  • 03 04:写入数据 3(2 字节)
  • 75 F5:CRC 校验

更详细的格式如下:

从设备地址 + 功能码 + 起始寄存器地址(高位)+ 起始寄存器地址(低位) + 寄存器数量(高位) + 寄存器数量(低位) + 数据总字节数 + [N 组写入值(每组 2 字节)] + CRC 高位 + CRC 低位

响应数据

01 10 00 02 00 03 A7 3C
  • 01:从设备地址(1-247)
  • 10:功能码(写保持寄存器)
  • 00 02:起始寄存器地址(2 字节)
  • 00 03:寄存器数量
  • A7 3C:CRC 校验

更详细的格式如下:

从设备地址 + 功能码 + 起始寄存器地址(高位)+ 起始寄存器地址(低位) + 寄存器数量(高位) + 寄存器数量(低位) + CRC 高位 + CRC 低位。

### Modbus RTU 协议简介 Modbus 是一种工业标准通信协议,广泛用于自动化领域,特别是在 PLC 和其他工业设备之间的数据交换。作为一种主从架构的协议Modbus 支持多个物理层和传输介质,包括但不限于 RS232、RS485 及 TCP/IP 等[^3]。 #### 特点与优势 - **开放性和兼容性**:作为一个公开的标准,Modbus 不受特定厂商限制,适用于广泛的硬件平台。 - **简易性**:其命令结构相对简单,便于开发者理解和实施。 - **灵活性**:支持多种物理接口,并能适应不同的网络环境。 - **广泛应用场景**:不仅限于传统制造业,在楼宇自动化等领域也有着重要地位[^5]. ### 使用教程概览 对于希望学习如何在不同平台上部署 Modbus RTU 的用户来说,存在多份详尽的教学资料可供参考: - 对于 CODESYS 用户而言,《CODESYS Modbus RTU 使用指南》涵盖了从基础理论到具体操作流程的内容,指导使用者完成必要的设置并解决可能出现的问题[^2]. - 针对 Siemens S7-1500 PLC 平台,则有专门针对此型号编写的《S7-1500PLC Modbus-RTU 通信详解》,它深入探讨了该系列产品的特性及其在网络集成方面的最佳实践方法[^4]. 此外,《LabVIEW Modbus RTU 实例讲解》为图形化编程爱好者提供了一套完整的案例分析,通过具体的工程实例来展示如何运用 LabVIEW 工具包实现高效的 Modbus RTU 数据交互过程[^1]. ### 示例代码片段 下面给出一段 Python 中基于 pyserial 库实现基本读取寄存器功能的例子: ```python import serial from pymodbus.client.sync import ModbusSerialClient as ModbusClient client = ModbusClient(method='rtu', port='/dev/ttyUSB0', baudrate=9600) if client.connect(): result = client.read_holding_registers(address=0x00, count=10, unit=1) print(result.registers) else: print('Connection failed') client.close() ``` 这段程序展示了怎样建立一个简单的客户端连接至指定端口上的服务器节点,并尝试获取一组保持寄存器内的数值信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值