使用C中的Modbus创建一个简单的客户端/服务器

Pig*_*ius 9 c network-programming modbus serial-communication modbus-tcp

我目前正在开发一个允许不同自动化进行通信的项目.为此,我想创建一个客户端和服务器,使用modbus协议进行通信.我不确定我现在是否想要使用ModBus/TCP,ModBus/RTU或ModBus/ASCII.

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

我要的是,如果有人能给我一个用C语言编写的简单代码用于客户端和/或使用Modbus进行通信的服务器,因为我不确定我将使用任何类型的Modbus将是一个很大的帮助(RTU/TCP/ASCII).

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

非常感谢您的宝贵时间.

mat*_*pop 12

三件事:

  1. 在您开发自己的客户端和服务器组件时,我建议您仅在严格要求或方便开放时使用Modbus(即其他制造商必须能够通过标准化协议与您的客户端或服务器组件通信 - 和Modbus适合).
  2. 请注意,Modbus TCP不仅仅是TCP/IP上的Modbus RTU(/ ASCII)(当然,也允许使用UDP).需要考虑一些重要的差异.
  3. 我知道您需要更深入地了解Modbus.此时,一旦在C程序中有一个开放的串行通道或(监听)TCP套接字,您可以从简单的Modbus请求/响应开始.

看看这个简短但相当完整的描述,以及这个不断更新的库的文档.


这是一个基于libmodbus的 Linux的超简化RTU示例.
请给我一些C99放松的紧凑性.
在现实世界中,您还应该正确处理SIGTERM等信号...... 对于Linux内核2.6.28以上,
还有一个modbus_rtu_set_serial_mode(RS232 vs 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);
Run Code Online (Sandbox Code Playgroud)

奴隶片段

//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);
Run Code Online (Sandbox Code Playgroud)

  • 你不需要感谢我......因为我是蝙蝠侠!! >:| (4认同)
  • 非常感谢你的回答,我正在寻求希望.我被迫使用modbus,即使我不是我正在研究的情况,也可以使用modbus或者逻辑解决方案.是的我明白Modbus TCp不是RTU或TCP over TCP,我的意思是modbus TCP就像任何TCP通信一样,唯一的区别是数据结构(对吗?).谢谢你的链接,我已经有了modbus库,但我真的很想在C中没有使用任何库的例子. (2认同)
  • 非常感谢你的代码,我会尽快实现它,我很惊讶你帮助我的时间,我非常感谢你. (2认同)