本文介绍了RS485:设备的 ioctl 不合适的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用以下代码访问 RS485 从站,但出现错误:

I am using the following code to access the RS485 slave but I get the error:

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

我的代码如下:

#include <linux/serial.h>
#include <sys/ioctl.h>


    int fd = open ("/dev/ttyUSB0", O_RDWR);
    if (fd < 0) {
        printf("Error Opening
");
        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
",  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
",  errno, strerror( errno ));
    }

我从 https://www.kernel 获取源代码.org/doc/Documentation/serial/serial-rs485.txt.我正在树莓派上开发我的应用程序,并使用 Quad RS232-HS 芯片连接到 FTDI USB 串行设备.错误的根源是什么?

I took the source code from https://www.kernel.org/doc/Documentation/serial/serial-rs485.txt. I am developing my application on the raspberry pi and am connected to the FTDI USB Serial device using Quad RS232-HS chip. What might be the source of the error?

当USB我连接USB设备时,输出为

When USB I connect the USB device, output for

dmesg

如下:

[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

推荐答案

正如@Richard Chambers 在评论中提到的,您正在使用未初始化的结构.你应该这样做

As mentioned in the comment by @Richard Chambers you are using the structure uninitialised. You should do

struct serial_rs485 rs485conf = {0};

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

However, as discussed that didn't solve the problem.

引用您引用的内核文档

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

然而,该设备有一个专用引脚,称为 TXDEN.引用自 数据表部分4.3.3

However this device has a dedicated pin called TXDEN for that. Quoting from the Data sheet section 4.3.3

采用RS485,发送器仅在从 UART 传输字符时启用.FT4232H 上的 TXDEN 引脚是正是为此目的而提供的,因此发送器使能连接到 TXDEN

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

and you can see that the RS232 outputs RTS / DTR not connected in RS485, this is in contrast to devices where RTS becomes TXDEN which would require an intervention by the driver.

如果我们将 struct serial_rs485 分开,我们可以看到它主要是为了达到此目的而控制 RTS.由于该设备具有专用的 TXDEN 引脚,因此这些控制字段无关紧要.

If we pick apart struct serial_rs485 we can see that it is mostly about controlling RTS for this purpose. Since this device has a dedicated TXDEN pin, those control fields are irrelevant.

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

Another flag that is used in this structure:

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

是的,看看电路,您在线上发布的内容也会收到.看起来你不能关闭它.RS485 是多点的,所以你应该过滤掉那些无论如何都不是发给你的消息.其中一些消息可能来自您的事实并不重要.

And yes looking at the circuit, what you put out on the line you will also receive. Looks like you cannot turn that off. RS485 is multidrop, so you should be filtering out messages that were not addressed to you anyway. The fact that some of those messages may have originated from you doesn't matter.

最后(也是第一次)我们有了这个

Finally (and firstly) we have this

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

这真的是在说启用由该结构控制的所有 RS485 特定的东西".除了我们刚刚让所有这些东西变得无关紧要之外,因此启用它没有任何效果.

That's really saying "enable all the RS485-specific stuff that's controlled by this structure". Except that we've just made all that stuff irrelevant, so enabling it has no effect.

这就是未为该 UART 实现 ioctl 的原因.

This is why the ioctl is not implemented for that UART.

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

You have a number of options, these are just suggestions so pick what suits you

  • 删除这部分不需要的初始化代码
  • 有条件地编译#if RS485_IOCTLS
  • 有条件地运行它
  • errnoENOTTY 视为表明,在这种情况下 ioctl 不是必需的,实际上您可以继续没有错误
  • Delete this section of the initializtion code as it's not needed
  • Compile it conditionally #if RS485_IOCTLS
  • Run it conditionally
  • Treat that errno value ENOTTY as indicating that, in this context the ioctl was not required and you can in fact proceed as if there was no error

这篇关于RS485:设备的 ioctl 不合适的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-16 10:12