2

我正在尝试在我的程序中设置半双工通信。我的 RS485 收发器使用 RTS 标志 (TIOCM_RTS) 在发送和接收之间来回切换。要发送/接收数据,我需要手动更改 RTS 标志:

  1. 将 RTS 设置为高。

  2. 发送数据。

  3. 将 RTS 设置为低。

    int setRTS(int level) {
        int status;
        ioctl(ser_port, TIOCMGET, &status);
        if(level) {
            status |= TIOCM_RTS;
        } else {
            status &= ~TIOCM_RTS;
        }
        ioctl(ser_port, TIOCMSET, &status);
        return 1;
    }
    

我的问题是:linux内核不应该能够自动切换RTS吗?以及如何确保在调用 setRTS(0) 之前发送了数据?

4

2 回答 2

4

linux内核不应该能够自动切换RTS吗?

是的,从 Linux 3.0 开始就有这个内核框架。include/uapi/asm-generic/ioctls.h
中有两个 ioctl :

#define TIOCGRS485      0x542E
#define TIOCSRS485      0x542F

在 RS-485 模式下检索和配置 tty 串行端口驱动程序。
这些 ioctl 使用struct serial_rs485

 /*
  * Serial interface for controlling RS485 settings on chips with suitable
  * support. Set with TIOCSRS485 and get with TIOCGRS485 if supported by your
  * platform. The set function returns the new state, with any unsupported bits
  * reverted appropriately.
  */

 struct serial_rs485 {
         __u32   flags;                  /* RS485 feature flags */
 #define SER_RS485_ENABLED               (1 << 0)        /* If enabled */
 #define SER_RS485_RTS_ON_SEND           (1 << 1)        /* Logical level for
                                                            RTS pin when
                                                            sending */
 #define SER_RS485_RTS_AFTER_SEND        (1 << 2)        /* Logical level for
                                                            RTS pin after sent*/
 #define SER_RS485_RX_DURING_TX          (1 << 4)
         __u32   delay_rts_before_send;  /* Delay before send (milliseconds) */
         __u32   delay_rts_after_send;   /* Delay after send (milliseconds) */
         __u32   padding[5];             /* Memory is cheap, new structs
                                            are a royal PITA .. */
 };

我已经在 Atmel 和 Etrax SoC 上使用了这个 RS-485 功能,但是在 Linux UART/USART 驱动程序中这些 ioctl 的实现非常稀疏。
如果您的驱动程序没有它,那么请考虑自己实现它。您可以使用drivers/tty/serial/atmel_serial.c中的实现作为指导。另请阅读RS485 的 Linux 内核文档

于 2014-08-11T21:50:38.330 回答
1

这确实很棘手 - 要主动执行此操作,您需要知道最后一个字节何时清除 UART 引擎,或者至少何时进入(当缓冲区为空时)并添加根据波特率和字长计算的延迟. 这确实是值得在串行驱动程序本身中实现的东西,所有这些都是可见的。

但是,这个问题最常出现在共享总线上,在该总线上您还接收传输的所有内容。如果是这种情况,您可以使用接收自己的传输结束(假设您及时发现)作为禁用驱动程序的触发器。

于 2014-08-11T19:33:23.693 回答