首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >RS485:不适合于设备的ioctl

RS485:不适合于设备的ioctl
EN

Stack Overflow用户
提问于 2017-08-30 09:57:23
回答 2查看 8.3K关注 0票数 2

我使用以下代码访问RS485从服务器,但我得到了错误:

读取ioctl端口(25)时出错:不适合设备的ioctl

我的代码如下:

代码语言:javascript
运行
复制
#include <linux/serial.h>
#include <sys/ioctl.h>


    int fd = open ("/dev/ttyUSB0", O_RDWR);
    if (fd < 0) {
        printf("Error Opening\n");
        exit(0);
    }

    struct serial_rs485 rs485conf;

    /* Enable RS485 mode: */
    rs485conf.flags |= SER_RS485_ENABLED;

    /* Set logical level for RTS pin equal to 1 when sending: */
    rs485conf.flags |= SER_RS485_RTS_ON_SEND;

    /* set logical level for RTS pin equal to 0 after sending: */
    rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND);

    /* Set rts delay before send, if needed: */
    rs485conf.delay_rts_before_send = 0;

    /* Set rts delay after send, if needed: */
    rs485conf.delay_rts_after_send = 0;

    /* Set this flag if you want to receive data even whilst sending data */
    rs485conf.flags |= SER_RS485_RX_DURING_TX;

    if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) {
        fprintf( stderr, "Error reading ioctl port (%d): %s\n",  errno, strerror( errno ));
        exit(0);
    }

    //TODO read and write

    /* Close the device when finished: */
    if (close (fd) < 0) {
        fprintf( stderr, "Error closing device connection (%d): %s\n",  errno, strerror( errno ));
    }

我从https://www.kernel.org/doc/Documentation/serial/serial-rs485.txt获取了源代码。我正在开发我的应用程序在覆盆子π,并连接到FTDI USB串行设备使用Quad HS 232-HS芯片。错误的来源可能是什么?

当USB i连接USB设备时,输出

德梅斯

现如下:

代码语言:javascript
运行
复制
[16865.640038] usb 3-2: new high-speed USB device number 10 using xhci_hcd
[16865.780365] usb 3-2: New USB device found, idVendor=0403, idProduct=6011
[16865.780367] usb 3-2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[16865.780369] usb 3-2: Product: Quad RS232-HS
[16865.780370] usb 3-2: Manufacturer: FTDI
[16866.377940] usbcore: registered new interface driver usbserial
[16866.377969] usbcore: registered new interface driver usbserial_generic
[16866.377994] usbserial: USB Serial support registered for generic
[16866.384018] usbcore: registered new interface driver ftdi_sio
[16866.384045] usbserial: USB Serial support registered for FTDI USB Serial Device
[16866.384203] ftdi_sio 3-2:1.0: FTDI USB Serial Device converter detected
[16866.384247] usb 3-2: Detected FT4232H
[16866.384373] usb 3-2: FTDI USB Serial Device converter now attached to ttyUSB0
[16866.384399] ftdi_sio 3-2:1.1: FTDI USB Serial Device converter detected
[16866.384431] usb 3-2: Detected FT4232H
[16866.384727] usb 3-2: FTDI USB Serial Device converter now attached to ttyUSB1
[16866.384751] ftdi_sio 3-2:1.2: FTDI USB Serial Device converter detected
[16866.384786] usb 3-2: Detected FT4232H
[16866.384897] usb 3-2: FTDI USB Serial Device converter now attached to ttyUSB2
[16866.384917] ftdi_sio 3-2:1.3: FTDI USB Serial Device converter detected
[16866.384950] usb 3-2: Detected FT4232H
[16866.385385] usb 3-2: FTDI USB Serial Device converter now attached to ttyUSB3
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-08-30 11:45:21

正如“理查德钱伯斯”评论中提到的那样,你使用的是未初始化的结构。你应该这么做

代码语言:javascript
运行
复制
struct serial_rs485 rs485conf = {0};

然而,正如所讨论的那样,这并没有解决问题。

引用您引用的内核文档

一些CPU/UART(例如Atmel AT91或16C950 UART)包含一个内置的半双工模式,能够通过切换RTS或DTR信号自动控制线路方向。可用于控制外部半双工硬件,如RS485收发器.

然而,这个设备有一个专用的引脚,名为TXDEN。引用数据表第4.3.3节的话

使用RS485,只有当字符从UART发送时才启用发射机。FT4232H上的TXDEN引脚正是为此目的而提供的,因此发射机启用的是连接到TXDEN上的。

您可以看到,RS232输出RS485中没有连接的RTS / DTR,这与RTS成为TXDEN的设备形成对比,后者需要驱动程序的干预。

如果我们拆开struct serial_rs485,我们可以看到,它主要是为了这个目的而控制RTS。因为这个设备有一个专用的TXDEN引脚,所以这些控制字段是无关的。

在此结构中使用的另一个标志:

代码语言:javascript
运行
复制
  /* Set this flag if you want to receive data even whilst sending data */
rs485conf.flags |= SER_RS485_RX_DURING_TX;

是的,看看电路,你在线路上的输出也会收到。看来你不能关掉它。RS485是多重拖放的,所以您应该过滤出没有发送给您的消息。事实上,这些信息中的一些可能来自于您,这并不重要。

最后(首先)我们有了这个

代码语言:javascript
运行
复制
/* Enable RS485 mode: */
rs485conf.flags |= SER_RS485_ENABLED;

这实际上是说“启用由这个结构控制的所有‘s 485特定的东西”。只不过我们刚刚把所有的东西都变得无关紧要了,所以启用它是没有效果的。

这就是为什么ioctl没有为该UART实现的原因。

你有很多选择,这些只是建议,所以选择适合你的

  • 如果不需要,请删除初始化代码的这一部分
  • 有条件地编译#if RS485_IOCTLS
  • 有条件地运行它
  • 将该errnoENOTTY视为指示在此上下文中不需要ioctl,您实际上可以继续进行,就好像没有错误一样。
票数 2
EN

Stack Overflow用户

发布于 2019-05-09 20:17:01

我认为,对未来面临类似问题的其他人来说,从硬件方面更详细地阐述罗德尼的答案可能会增加一些价值。

虽然我来到这里是为了寻找线程问题的答案(为什么我在试图激活pyserial上的RS485模式(实际上是从pyModbus调用)时遇到了ioctl错误),但我还是找到了上面这个问题的答案。简单明了,并提供一个比罗德尼的更短的答案:你不能。你将无法激活你的RS485模式在你的FTDI,因为没有功能使用RTS信号作为驱动器为您的RS485芯片启用。

有些设备,比如那些使用atmel_serial驱动程序的设备,确实实现了这个功能,但是您不会发现那么多。深入研究这个问题,您会发现有人说您可以根据支持RS485模式的驱动程序之一编写自己的驱动程序(例如,参见:RS-485通信中RTS的自动更改,但在我看来,它们是错误的)

现在有了坏消息,您可以问自己为什么需要使用RS485模式?我想,就像我一样,您试图使用双线RS485设置在两个设备之间建立一个半双工链路(这在许多工业设备中是非常频繁的,在这些设备中,您有主从配置,其中一方发送数据请求,另一方相应地响应,就像使用Modbus一样)。

如果您正在寻找一个软件解决方案,您仍然可以采取RTS信号高低手动启动和完成发送后,从双方。这个解决方案在大多数环境中都适用于测试和娱乐(至少在我尝试过的那些环境中,它甚至可以在Raspberry Pi上使用GPIO行来控制驱动器启用/~读取启用信号),但是如果您想获得良好的可靠性,我不会使用它。与任何非实时操作系统,没有保证,您将得到正确的时间和一些设备是相当挑剔的,并将报告一个超时错误。如果你可以自由地选择公共汽车的两边(如果你有两个以上的话),你可以随时增加你在任何地方的车次,并希望得到最好的结果。

好消息是,正如罗德尼所说,在FTDI芯片上,您有TXDEN信号在pin 13上可用,所以您可以立即使用。不幸的是,大多数廉价的USB到串行适配器PCBs没有这个信号在板上容易访问。我的扑克板就是这样发生的。如果您没有准备好直接将电缆附加到SMD IC上,您可以做我所做的事情:从FTDI下载mprog 3.5,连接到EPROM,在I/O控件下选择TXDEN而不是TXLED,然后单击保存将更新的固件写入芯片。然后,您可以轻松地将电缆连接到LED盘上,并将其用作驱动器启用/~读取启用信号(见图片,范围快照显示它工作得很好)。

在TXLED上用TXDEN信号改进FTDI板

修改电路的范围捕获:蓝色为TX,黄色TXDEN

最后,如果您运气不好,遇到其他没有此选项( TXDEN )的芯片(如PL2303 ),您可以使用555定时器构建硬件TXDEN(参见此处:RS485.pdf)。我测试了这个电路,它运行良好,至少在9600 bps (注意,我必须使用一个39K电阻,而不是一个3.9K,我认为这是一个错误,但我可能错了,我没有深入细节,我只是需要一些快速和肮脏的配对与我的FTDI。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45957314

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档