Modbus协议

本文介绍了Modbus,一种在工业自动化中广泛应用的通信协议,重点讲解了ModbusRTU和ModbusTCP的原理、数据格式以及在实际应用中的案例,包括串口和网络通信的示例代码。
摘要由CSDN通过智能技术生成

Modbus

Modbus是一种用于工业自动化领域的通信协议,广泛应用于监控、控制和数据采集等领域。它是一种简单、开放、易于实现和部署的通信协议,由Modicon(现在的施耐德电气)于1979年创建,用于在PLC(可编程逻辑控制器)和其他电子设备之间进行通信。

Modbus协议通常在串口(例如RS-232、RS-485)或以太网等物理介质上进行通信。它采用了主从结构,其中一个设备(主站)向一个或多个设备(从站)发送请求,并从从站接收响应。

Modbus协议包括多个变体,其中最常见的是以下两种:

  1. Modbus RTU:RTU(Remote Terminal Unit)是一种二进制格式的Modbus协议,数据以二进制形式传输,通常在串口通信中使用,具有较高的抗干扰能力和较短的响应时间。
  2. Modbus TCP:TCP(Transmission Control Protocol)是一种基于TCP/IP网络的Modbus协议,数据以ASCII或二进制形式封装在TCP/IP数据包中传输,通常在以太网通信中使用,具有更高的速度和更广泛的应用范围。

Modbus RTU和Modbus TCP 数据格式

  1. Modbus RTU 数据格式:
    Modbus RTU使用二进制格式传输数据,通常在串口通信中使用。其数据帧格式如下:
    起始位:一个起始位,通常为逻辑低电平。
    地址字段:8位,用于指定从站地址。
    功能码:8位,用于指定请求的功能。
    数据字段:0至252字节的数据,包括数据和校验字段。
    CRC校验:16位循环冗余校验,用于校验数据的完整性。
    停止位:一个或两个停止位,通常为逻辑高电平。
    Modbus RTU的数据传输速率通常在2400bps至115200bps之间,具体取决于通信的要求和设备的支持能力。

  2. Modbus TCP 数据格式:
    Modbus TCP是基于TCP/IP网络的Modbus协议,数据以ASCII或二进制形式封装在TCP/IP数据包中传输。其数据帧格式如下:
    TCP报文头部:包含源IP地址、目标IP地址、源端口号和目标端口号等信息。
    Modbus应用数据单元(ADU):包含Modbus功能码、数据字段和可选的错误检查字段。
    协议标识符(Protocol Identifier):16位,指示Modbus协议版本。
    数据长度字段:16位,指示ADU的长度。
    单元标识符(Unit Identifier):8位,用于指定从站地址。
    功能码:8位,用于指定请求的功能。
    数据字段:根据功能码不同,可以是读请求、写请求等操作的参数。
    CRC校验(对于Modbus RTU over TCP):16位循环冗余校验,用于校验ADU的完整性。
    Modbus TCP使用标准的TCP/IP网络进行通信,因此可以利用现有的网络设备和基础设施,通常使用标准的以太网物理层和TCP/IP协议栈。

以下是一个简单的Modbus RTU和Modbus TCP的案例:

Modbus RTU 案例:

假设你有一个串口设备(例如串口转以太网适配器)连接到你的计算机,并且该设备支持Modbus RTU通信协议。你想通过串口与该设备通信,并读取其寄存器中的数据。

#include <iostream>
#include <modbus/modbus-rtu.h>

int main() {
    modbus_t *ctx = modbus_new_rtu("/dev/ttyS0", 9600, 'N', 8, 1);
    if (ctx == nullptr) {
        std::cerr << "Unable to create Modbus RTU context" << std::endl;
        return -1;
    }

    if (modbus_connect(ctx) == -1) {
        std::cerr << "Connection failed: " << modbus_strerror(errno) << std::endl;
        modbus_free(ctx);
        return -1;
    }

    uint16_t data[32];
    int rc = modbus_read_registers(ctx, 0, 10, data);
    if (rc == -1) {
        std::cerr << "Read failed: " << modbus_strerror(errno) << std::endl;
    } else {
        for (int i = 0; i < rc; ++i) {
            std::cout << "Register " << i << ": " << data[i] << std::endl;
        }
    }

    modbus_close(ctx);
    modbus_free(ctx);
    return 0;
}

Modbus TCP 案例:

假设你有一个Modbus TCP从站设备连接到你的局域网,并且你知道它的IP地址和端口号。你想通过网络与该设备通信,并读取其寄存器中的数据。

#include <iostream>
#include <modbus/modbus-tcp.h>

int main() {
    modbus_t *ctx = modbus_new_tcp("192.168.1.100", 502);
    if (ctx == nullptr) {
        std::cerr << "Unable to create Modbus TCP context" << std::endl;
        return -1;
    }

    if (modbus_connect(ctx) == -1) {
        std::cerr << "Connection failed: " << modbus_strerror(errno) << std::endl;
        modbus_free(ctx);
        return -1;
    }

    uint16_t data[32];
    int rc = modbus_read_registers(ctx, 0, 10, data);
    if (rc == -1) {
        std::cerr << "Read failed: " << modbus_strerror(errno) << std::endl;
    } else {
        for (int i = 0; i < rc; ++i) {
            std::cout << "Register " << i << ": " << data[i] << std::endl;
        }
    }

    modbus_close(ctx);
    modbus_free(ctx);
    return 0;
}

以上示例仅供参考,实际使用时需要根据你的设备和环境进行调整和修改。

  • 11
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值