Detailed explanation of Modbus TCP protocol and C language example

insert image description here
Modbus TCP is a communication protocol applied to Ethernet, based on Modbus RTU protocol. The Modbus protocol is a protocol applied to serial data communication and is widely used in industrial control systems. Modbus TCP encapsulates traditional Modbus RTU messages in TCP/IP telegrams, enabling it to communicate in modern Ethernet environments. This article will introduce the message format of the Modbus TCP protocol in detail, the specific meaning of each part, and give an example in C language.

Modbus TCP message format

Modbus TCP message mainly includes the following parts:

  1. Transaction Identifier: 2 bytes
  2. Protocol Identifier: 2 bytes
  3. Length: 2 bytes
  4. Unit Identifier: 1 byte
  5. Function Code: 1 byte
  6. Data (Data): n bytes

1. Transaction identifier

Transaction identifiers are used to identify request/response message pairs. The client generates a unique transaction identifier when it initiates the request, and the server responds with the same transaction identifier. This enables the client to distinguish and properly handle concurrent requests.

2. Protocol Identifier

Protocol identifiers are used to distinguish different upper layer protocols. For Modbus TCP, the protocol identifier is fixed at 0x0000.

3. Length

The length field indicates the total number of bytes of the message starting from the unit identifier. Contains unit identifier, function code and data fields.

4. Unit identifier

A unit identifier is used to identify a specific unit within a device. In Modbus TCP, the unit identifier corresponds to the device address in Modbus RTU.

5. Function code

The function code is used to indicate the operation type of the message. Such as reading holding registers, writing single registers, etc. Common function codes are:

  • 0x03: Read holding register
  • 0x06: Write a single register
  • 0x10: Write multiple registers

6. Data

The content of the data field depends on the function code. For example, for a read holding register operation, the data field contains the starting register address and the number of registers to read.

C language example

Here is an example of a Modbus TCP client implemented in C to read holding registers:

#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;
}

The above example creates a TCP client to connect to the Modbus TCP server with IP address "192.168.1.100" and port number 502. Then construct a request message to read the holding register and send it to the server. Receive and parse the response message from the server, and finally output the register value.

Please note that this example is for demonstration purposes only, real application may need to consider more error handling and functionality. In actual projects, existing Modbus TCP libraries, such as libmodbus, can be used to handle Modbus TCP communication more conveniently and safely.

[The last bug] There are updates and releases on multiple platforms. You can connect three times with one click, follow + star, and don't miss exciting content~
insert image description here

Guess you like

Origin blog.csdn.net/qq_33471732/article/details/131316853