Modbus TCP 协议详解及C语言示例

在这里插入图片描述
Modbus TCP 是一种应用于以太网的通讯协议,基于Modbus RTU协议。Modbus协议是一种应用于串行数据通信的协议,广泛应用于工业控制系统。Modbus TCP 将传统的 Modbus RTU 消息封装在 TCP/IP 报文中,使其能够在现代的以太网环境中进行通信。本文将详细介绍 Modbus TCP 协议的报文格式、各部分具体含义,并给出 C 语言的示例。

Modbus TCP 报文格式

Modbus TCP 报文主要包含以下部分:

  1. 事务标识符(Transaction Identifier):2 字节
  2. 协议标识符(Protocol Identifier):2 字节
  3. 长度(Length):2 字节
  4. 单元标识符(Unit Identifier):1 字节
  5. 功能码(Function Code):1 字节
  6. 数据(Data):n 字节

1. 事务标识符

事务标识符用于标识请求/响应报文对。客户端发起请求时生成一个唯一的事务标识符,服务器响应时使用相同的事务标识符。这使得客户端能够区分并正确处理并发请求。

2. 协议标识符

协议标识符用于区分不同的上层协议。对于 Modbus TCP 来说,协议标识符固定为 0x0000。

3. 长度

长度字段表示从单元标识符开始的报文总字节数。包括单元标识符、功能码和数据字段。

4. 单元标识符

单元标识符用于标识设备中的特定单元。在 Modbus TCP 中,单元标识符对应于 Modbus RTU 中的设备地址。

5. 功能码

功能码用于指示报文的操作类型。如读取保持寄存器、写入单个寄存器等。常见的功能码有:

  • 0x03:读取保持寄存器
  • 0x06:写入单个寄存器
  • 0x10:写入多个寄存器

6. 数据

数据字段的内容取决于功能码。例如,对于读取保持寄存器操作,数据字段包含起始寄存器地址和要读取的寄存器数量。

C 语言示例

以下是一个使用 C 语言实现的 Modbus TCP 客户端示例,用于读取保持寄存器:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define BUFFER_SIZE 1024

int main() {
    
    
    int client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (client_socket == -1) {
    
    
        perror("socket");
        exit(1);
    }

    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("192.168.1.100");
    server_addr.sin_port = htons(502);

    if (connect(client_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
    
    
        perror("connect");
        exit(1);
    }

    // 构建 Modbus TCP 读取保持寄存器请求报文
    unsigned char request[12] = {
    
    
        0x00, 0x01, // 事务标识符
        0x00, 0x00, // 协议标识符
        0x00, 0x06, // 长度
        0x01,       // 单元标识符
        0x03,       // 功能码:读取保持寄存器
        0x00, 0x00, // 起始寄存器地址
        0x00, 0x01  // 要读取的寄存器数量
    };

    // 发送请求报文
    if (write(client_socket, request, sizeof(request)) == -1) {
    
    
        perror("write");
        exit(1);
    }

    // 接收响应报文
    unsigned char response[BUFFER_SIZE];
    int response_length = read(client_socket, response, BUFFER_SIZE);
    if (response_length == -1) {
    
    
        perror("read");
        exit(1);
    }

    // 解析响应报文
    if (response[7] != 0x03) {
    
    
        printf("Error: Invalid function code in response.\n");
        exit(1);
    }
    if (response[8] != 0x02) {
    
    
        printf("Error: Invalid data length in response.\n");
        exit(1);
    }

    int register_value = (response[9] << 8) | response[10];
    printf("Register value: %d\n", register_value);

    close(client_socket);
    return 0;
}

以上示例创建一个 TCP 客户端,连接到 IP 地址为 “192.168.1.100”、端口号为 502 的 Modbus TCP 服务器。然后构造一个读取保持寄存器的请求报文,并发送到服务器。接收并解析服务器的响应报文,最后输出寄存器值。

请注意,此示例仅用于演示目的,实际应用可能需要考虑更多的错误处理和功能。在实际项目中,可以使用现有的 Modbus TCP 库,例如 libmodbus,以便更方便且安全地处理 Modbus TCP 通信。

【最后一个bug】多平台都有更新和发布,大家可以一键三连,关注+星标,不错过精彩内容~
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_33471732/article/details/131316853