首页 > 解决方案 > 如何解决 Linux 和 Modbus 的错误文件描述符

问题描述

我正在尝试在运行 Raspian Buster 的 Raspberry Pi 上使用 libmodbus 设置半双工 RS-485 通信,并带有 FTDI USB 到串行适配器。当我运行 ls /dev/ 时,我的 FTDI 适配器显示为 ttyUSB0。

我尝试了以下示例代码:

#include <modbus.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

int main(void) {
   modbus_t *ctx  = modbus_new_rtu("/dev/ttyUSB0", 19200, 'N', 8, 1);
    if (ctx == NULL) {
        fprintf(stderr, "Unable to create the libmodbus context\n");
        return 0;
    }

    if (modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS485) == -1) {
        fprintf(stderr, "Error setting the serial port as RS-485\n");
        fprintf(stderr, "errno: %d\n (EBADF == 9)", errno);
        modbus_free(ctx);
        return 0;
    }
}

编译gcc test1.c -I/usr/include/modbus -lmodbus。我得到errnoas9EBADF,即使我使用sudo.

标签: linuxmodbusrs485

解决方案


您的问题有一个非常简单的解决方案:只是不要设置MODBUS_RTU_RS485,很可能您不需要它。

对于没有自动(硬件)方向控制的设备,这种模式实际上是一种解决方法。如您所知,Modbus RTU 在半双工 RS485 链路上工作(只允许一个设备通话,而所有其他设备必须只监听),因此需要一个额外的(到 RX 和 TX)信号来控制正在写入的设备总线始终(方向控制)。

因此,您只需要在MODBUS_RTU_RS485您的设备缺少此功能时进行设置,这在现在是不太可能的,或者您正在构建自己的收发器。特别是大多数基于 FTDI 芯片的设备都应该具有此功能,因为芯片本身具有 TXDEN(发送使能)引脚。有关更多详细信息和将 TXDEN 信号暴露给非默认引脚的技巧,请参见此处。

当您没有此功能时(一种常见的情况是,当您想使用 Rpi 上的嵌入式 UART 用于 RS485 上的 Modbus,实现您自己的收发器)时,您需要软件(或硬件)解决方法。这就是MODBUS_RTU_RS485应该派上用场的地方,重新利用 RTS 流控制信号。不幸的是,大多数串行驱动程序(包括ftdi_sio您可能正在使用的那个)不支持这种模式(再次参考上面的链接)。

幸运的是,该变通方法有一些变通方法:完整讨论请参见此处。您还可以查看这个答案,其中我解释了如何设置libmodbus以支持使用 Rpi 上的 GPIO 引脚切换总线上的方向(也适用于大多数 SBC,我已成功使用此方法与 Pocket以芯片计算机为例)。

您可以在其他地方找到有关此问题的更多背景信息:此处此处


推荐阅读