我目前正在从事一个项目,该项目将允许不同的自动化人员进行交流。为此,我想创建一个将使用modbus协议(protocol)进行通信的客户端和服务器。我不确定现在是否要使用ModBus/TCP,ModBus/RTU或ModBus/ASCII。

我在C中搜索了客户端/服务器示例,可以找到库,但没有简单的通信示例。我想从头开始,所以库不是我想要的。

我要问的是,是否有人可以给我一个用C语言编写的用于使用Modbus进行通信的客户端和/或服务器的简单代码,因为我不确定我将使用哪种类型的Modbus会带来很大的帮助(RTU/TCP/ASCII)。

越简单越好,例如,我希望代码演示:服务器初始化,请求,答案,关闭连接。

非常感谢您的宝贵时间。

最佳答案

三件事:

  • 在开发自己的客户端和服务器组件时,建议您仅在严格要求或出于开放的考虑而方便使用Modbus(即其他制造商必须能够通过标准化的方式与您的客户端或服务器组件进行通信)协议(protocol)-和Modbus匹配)。
  • 请注意,Modbus TCP不只是基于TCP/IP的Modbus RTU(/ASCII)(当然仍然允许,当然也可以允许UDP)。有一些重要的差异要考虑。
  • 我了解您需要更深入地了解Modbus。到那时,一旦在C程序中有了开放的串行 channel 或(监听)TCP套接字,就可以从简单的Modbus请求/响应开始。

  • 查看此short but quite complete description以及此constantly updated library的文档。

    这是一个基于libmodbus的 super 简化的Linux RTU示例。
    请允许我放松一下C99,以实现紧凑性。
    在现实世界中,您还应该正确处理SIGTERM等信号。
    从Linux 2.6.28开始,还有一个modbus_rtu_set_serial_mode(RS232与RS485)功能。您可能会发现其他使平台上使用RS485更加容易的库。

    主片段
    //Create a new RTU context with proper serial parameters (in this example,
    //device name /dev/ttyS0, baud rate 9600, no parity bit, 8 data bits, 1 stop bit)
    modbus_t *ctx = modbus_new_rtu("/dev/ttyS0", 9600, 'N', 8, 1);
    if (!ctx) {
        fprintf(stderr, "Failed to create the context: %s\n", modbus_strerror(errno));
        exit(1);
    }
    
    if (modbus_connect(ctx) == -1) {
        fprintf(stderr, "Unable to connect: %s\n", modbus_strerror(errno));
        modbus_free(ctx);
        exit(1);
    }
    
    //Set the Modbus address of the remote slave (to 3)
    modbus_set_slave(ctx, 3);
    
    
    uint16_t reg[5];// will store read registers values
    
    //Read 5 holding registers starting from address 10
    int num = modbus_read_registers(ctx, 10, 5, reg);
    if (num != 5) {// number of read registers is not the one expected
        fprintf(stderr, "Failed to read: %s\n", modbus_strerror(errno));
    }
    
    modbus_close(ctx);
    modbus_free(ctx);
    

    奴隶片段
    //Prepare a Modbus mapping with 30 holding registers
    //(plus no output coil, one input coil and two input registers)
    //This will also automatically set the value of each register to 0
    modbus_mapping_t *mapping = modbus_mapping_new(0, 1, 30, 2);
    if (!mapping) {
        fprintf(stderr, "Failed to allocate the mapping: %s\n", modbus_strerror(errno));
        exit(1);
    }
    
    
    //Example: set register 12 to integer value 623
    mapping->tab_registers[12] = 623;
    
    
    modbus_t *ctx = modbus_new_rtu("/dev/ttyS0", 9600, 'N', 8, 1);
    if (!ctx) {
        fprintf(stderr, "Failed to create the context: %s\n", modbus_strerror(errno));
        exit(1);
    }
    
    //Set the Modbus address of this slave (to 3)
    modbus_set_slave(ctx, 3);
    
    
    if (modbus_connect(ctx) == -1) {
        fprintf(stderr, "Unable to connect: %s\n", modbus_strerror(errno));
        modbus_free(ctx);
        exit(1);
    }
    
    
    uint8_t req[MODBUS_RTU_MAX_ADU_LENGTH];// request buffer
    int len;// length of the request/response
    
    while(1) {
        len = modbus_receive(ctx, req);
        if (len == -1) break;
    
        len = modbus_reply(ctx, req, len, mapping);
        if (len == -1) break;
    }
    printf("Exit the loop: %s\n", modbus_strerror(errno));
    
    modbus_mapping_free(mapping);
    modbus_close(ctx);
    modbus_free(ctx);
    

    关于在C中使用Modbus创建一个简单的客户端/服务器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29602698/

    10-11 21:40