簡體   English   中英

RS485:設備的不適當的ioctl

[英]RS485: Inappropriate ioctl for device

我正在使用以下代碼訪問RS485從站,但出現錯誤:

讀取ioctl端口(25)時出錯:設備的ioctl不適當

我的代碼如下:

#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獲取了源代碼。 我正在樹莓派上開發應用程序,並使用Quad RS232-HS芯片連接到FTDI USB串行設備。 錯誤的根源可能是什么?\\

當我連接USB設備時,輸出為

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

我認為,從硬件方面詳細說明羅德尼的答案可能會為將來面臨類似問題的其他人增加一些價值。

盡管我來這里是為了尋找線程問題的答案(為什么我在嘗試激活pyserial上的RS485模式時遇到ioctl錯誤(實際上是我從pyModbus調用的),但我在上面找到了該問題的答案。簡單明了,並且提供的答案比Rodney的答案短:您不能。您將無法激活FTDI上的RS485模式,因為沒有使用RTS信號作為RS485芯片的驅動使能的功能。

某些設備(例如使用atmel_serial驅動程序的設備)確實實現了此功能,但您找不到很多。 深入研究這個問題,您會發現有人說您可以基於支持RS485模式的驅動程序之一編寫自己的驅動程序(例如,請參見: 自動更改用於RS-485通訊的RTS ,但在我看來,這是錯誤的)

現在您有個壞消息,您可以問自己為什么要使用RS485模式? 我想像我一樣,您正在嘗試使用兩線RS485設置在兩個設備之間建立半雙工鏈接(令人驚訝的是,在許多工業設備中,您具有主從配置,並且您需要一側發送就像Modbus一樣,對數據的請求以及對方的正確響應)。

如果您正在尋找軟件解決方案,則仍然可以在開始和結束從每一側傳輸之后手動將RTS信號設為高電平和低電平。 該解決方案將在大多數環境中進行測試並使其有趣(至少在我嘗試過的環境中,它甚至可以在Raspberry Pi上與Python一起使用GPIO線來控制Drive Enable /〜Read Enable信號),但我不會使用它如果您想獲得良好的可靠性。 對於任何非實時操作系統,都沒有保修,您將獲得正確的時間,並且某些設備非常挑剔,並且會報告超時錯誤。 如果您可以自由選擇公交車的兩側(如果您有兩個以上的車站,則可以全部選擇),您可以隨時隨地增加平局 ,並希望最好。

正如羅德尼所說,好消息是,在FTDI芯片上,引腳13上有可用的TXDEN信號,因此您可以立即使用它。 不幸的是,大多數廉價的USB轉串行適配器PCB板上的信號都不容易訪問。 這就是我的Sparkfun董事會發生的事情。 如果您沒有挑戰直接將電纜連接到SMD IC的挑戰,則可以執行我的操作:從FTDI下載mprog 3.5,連接到EPROM,在I / O Controls下,選擇TXDEN而不是TXLED,然后單擊Save以寫入芯片的更新固件。 然后,您可以輕松地將電纜連接到LED焊盤,並將其用作驅動器啟用/〜讀取啟用信號(參見圖片,示波器快照顯示它很好地工作)。

修改后的FTDI板,在TXLED上帶有TXDEN信號

修改電路的示波器捕獲:藍色是TX,黃色TXDEN

最后,如果您不幸遇到其他沒有此選項的芯片(TXDEN),例如PL2303,您可以隨時學習,並使用555定時器構建硬件TXDEN(請參見此處: http:// www .embeddedsys.com / subpages / resources / images / documents / microsys_art_RS485.pdf )。 我測試了此電路,它至少在9600 bps時工作正常(請注意,我必須使用39K電阻器而不是3.9K電阻,我認為這是一個錯字,但我可能是錯的,我沒有詳細介紹,我只是需要快速又臟的東西來與我的FTDI配對。

如@Richard Chambers在評論中所述,您正在使用未初始化的結構。 你應該做

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引腳,因此這些控制字段無關緊要。

此結構中使用的另一個標志:

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

是的,看看電路,您在線路上的輸出也會收到。 看來您無法關閉它。 RS485是多點通信,因此您應該過濾掉未發送給您的消息。 這些消息中的某些消息可能源於您的事實並不重要。

最后(首先)我們有這個

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

這就是說“啟用由該結構控制的所有特定於RS485的東西”。 除了我們只是使所有這些東西無關緊要之外,因此啟用它沒有任何作用。

這就是為什么未為該UART實現ioctl的原因。

您有很多選擇,這些只是建議,因此請選擇適合您的選擇

  • 刪除不需要的初始化代碼部分
  • 有條件地編譯它#if RS485_IOCTLS
  • 有條件地運行
  • 將那個errnoENOTTY視為表明,在這種情況下不需要ioctl ,實際上您可以像沒有錯誤一樣繼續操作

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM