我目前正在开展一个项目,该项目将允许不同的自动化进行通信。为此,我想创建一个客户端和一个服务器,它们将使用 modbus 协议进行通信。我不确定我现在是否要使用 ModBus/TCP、ModBus/RTU 或 ModBus/ASCII。
我在 C 中搜索了客户端/服务器示例,我可以找到库,但没有简单的通信示例。我想从头开始,所以库不是我想要的。
我要问的是,是否有人可以给我一个用 C 编写的简单代码,用于使用 Modbus 进行通信的客户端和/或服务器,因为我不确定我将使用什么类型的 Modbus 会有很大帮助(RTU/TCP/ASCII)。
越简单越好,我希望代码演示的是,例如:对服务器的初始化、请求、应答、关闭连接。
非常感谢你的宝贵时间。
三件事:
看看这个简短但非常完整的描述,以及这个不断更新的库的文档。
这是一个基于libmodbus的 Linux 超级简化 RTU 示例。
请允许我放松一下 C99 以保持紧凑。
在现实世界中,你还应该正确处理 SIGTERM 等信号…… Linux 内核 2.6.28 及更高版本
还有一个(RS232 与 RS485)功能。modbus_rtu_set_serial_mode
你可能会发现其他库可以在你的平台上更轻松地使用 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);
非常感谢您的回答,我一直在寻找希望。我被迫使用 modbus,即使我不是我正在处理的情况,也使使用 modbus 成为合乎逻辑的解决方案。是的,我知道 Modbus TCp 不是 RTU 或 ASCII over TCP,我的意思是 modbus TCP 就像任何 TCP 通信一样,唯一的区别是数据结构(对吗?)。谢谢你的链接,我已经得到了 modbus 库,但我真的很想要一个不使用任何库的 C 示例。
好吧,他们解释了如何做到这一点,但我想要一个书面示例(最好是用 C 语言,但另一种语言也可以),以确保在我开始实现这个通信协议之前我理解正确。您似乎对 modbus 有所了解,也许您可以编写一个简短的代码来显示客户端和服务器之间的 modbus RTU 或 ASCII(我理解 modbus TCP)交互?我会爱你的!
只是更新一下,无论是 RTU 还是 ASCII,我仍然坚持使用 modbus 串行通信。
鉴于你所说的一切,最后我真的认为从头开始对你来说是非常不明智的。尽管了解 Modbus 协议变体的细节非常重要,但我建议您不要重新发明轮子,而是使用适合您平台的现有 C 库。只要有时间,我将发布一个基于 libmodbus 的简化 RTU 示例(ASCII 实际上是当今的传统)。在此类程序中,您只需引用操作系统设备名称(例如 /dev/ttyS0、COM6);让该设备作为 rs232/rs485 串行链路工作由您决定。
非常感谢你的代码,我会尽快实现它,我很惊讶你花时间帮助我,我非常感谢你。