RS485 串行通信

1. 简介

EIA-485,也称为 TIA/EIA-485 或 RS-485,是一种标准,定义了用于平衡数字多点系统中驱动器和接收器的电气特性。 该标准广泛用于工业自动化中的通信,因为它可以在长距离和电气噪声环境中有效使用。

3. 内核中已有的数据结构

Linux 内核提供了 struct serial_rs485 来处理 RS485 通信。 此数据结构用于设置和配置平台数据和 ioctl 中的 RS485 参数。

设备树还可以提供 RS485 启动时间参数 [1]。 当驱动程序调用 uart_get_rs485_mode() 时,串行核心会从设备树提供的值填充 struct serial_rs485

任何能够同时作为 RS232 和 RS485 工作的设备的驱动程序都应实现 rs485_config 回调并在 struct uart_port 中提供 rs485_supported。 串行核心调用 rs485_config 来执行设备特定部分,以响应 TIOCSRS485 ioctl(见下文)。 rs485_config 回调接收指向已清除的 struct serial_rs485 的指针。 在使用 rs485_supported 调用 rs485_config 之前,会清除用户空间提供的 struct serial_rs485rs485_supported 指示驱动程序对 struct uart_port 支持哪些 RS485 功能。 TIOCGRS485 ioctl 可用于读取与当前配置匹配的 struct serial_rs485

struct serial_rs485

用于控制 RS485 设置的串行接口。

定义:

struct serial_rs485 {
    __u32 flags;
#define SER_RS485_ENABLED               _BITUL(0);
#define SER_RS485_RTS_ON_SEND           _BITUL(1);
#define SER_RS485_RTS_AFTER_SEND        _BITUL(2);
#define SER_RS485_RX_DURING_TX          _BITUL(4);
#define SER_RS485_TERMINATE_BUS         _BITUL(5);
#define SER_RS485_ADDRB                 _BITUL(6);
#define SER_RS485_ADDR_RECV             _BITUL(7);
#define SER_RS485_ADDR_DEST             _BITUL(8);
#define SER_RS485_MODE_RS422            _BITUL(9);
    __u32 delay_rts_before_send;
    __u32 delay_rts_after_send;
    union {
        __u32 padding[5];
        struct {
            __u8 addr_recv;
            __u8 addr_dest;
            __u8 padding0[2];
            __u32 padding1[4];
        };
    };
};

成员

flags

RS485 功能标志。

delay_rts_before_send

发送前延迟(毫秒)。

delay_rts_after_send

发送后延迟(毫秒)。

{unnamed_union}

anonymous

padding

已弃用,请改用 padding0padding1。 请勿与 addr_recvaddr_dest 一起使用(由于重叠)。

{unnamed_struct}

anonymous

addr_recv

RS485 寻址模式的接收过滤器(仅当设置了 SER_RS485_ADDR_RECV 时使用)。

addr_dest

RS485 寻址模式的目标地址(仅当设置了 SER_RS485_ADDR_DEST 时使用)。

padding0

填充(设置为零)。

padding1

填充(设置为零)。

描述

用于控制具有合适支持的芯片上的 RS485 设置的串行接口。 如果您的平台支持,请使用 TIOCSRS485 进行设置,并使用 TIOCGRS485 进行获取。 设置函数返回新状态,所有不支持的位都会适当恢复。

标志位是

  • SER_RS485_ENABLED - 启用 RS485。

  • SER_RS485_RTS_ON_SEND - 发送时 RTS 引脚的逻辑电平。

  • SER_RS485_RTS_AFTER_SEND - 发送后 RTS 引脚的逻辑电平。

  • SER_RS485_RX_DURING_TX - 全双工 RS485 线路。

  • SER_RS485_TERMINATE_BUS - 启用总线端接(如果支持)。

  • SER_RS485_ADDRB - 启用 RS485 寻址模式。

  • SER_RS485_ADDR_RECV - 启用接收地址过滤器(启用 addr_recv)。 需要 SER_RS485_ADDRB

  • SER_RS485_ADDR_DEST - 目标地址(启用 addr_dest)。 需要 SER_RS485_ADDRB

  • SER_RS485_MODE_RS422 - 启用 RS422。 需要 SER_RS485_ENABLED

4. 从用户级别使用

从用户级别,可以使用之前的 ioctl 获取/设置 RS485 配置。 例如,要设置 RS485,您可以使用以下代码

#include <linux/serial.h>

/* Include definition for RS485 ioctls: TIOCGRS485 and TIOCSRS485 */
#include <sys/ioctl.h>

/* Open your specific device (e.g., /dev/mydevice): */
int fd = open ("/dev/mydevice", O_RDWR);
if (fd < 0) {
        /* Error handling. See errno. */
}

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;
/* or, set logical level for RTS pin equal to 0 when sending: */
rs485conf.flags &= ~(SER_RS485_RTS_ON_SEND);

/* Set logical level for RTS pin equal to 1 after sending: */
rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
/* or, 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 = ...;

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

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

if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) {
        /* Error handling. See errno. */
}

/* Use read() and write() syscalls here... */

/* Close the device when finished: */
if (close (fd) < 0) {
        /* Error handling. See errno. */
}

5. 多点寻址

Linux 内核为多点 RS-485 串行通信线路提供寻址模式。 寻址模式通过 struct serial_rs485 中的 SER_RS485_ADDRB 标志启用。 struct serial_rs485 具有两个额外的标志和字段,用于启用接收和目标地址。

地址模式标志
  • SER_RS485_ADDRB: 启用寻址模式(也在 termios 中设置 ADDRB)。

  • SER_RS485_ADDR_RECV: 启用接收(过滤)地址。

  • SER_RS485_ADDR_DEST: 设置目标地址。

地址字段(使用相应的 SER_RS485_ADDR_* 标志启用)
  • addr_recv: 接收地址。

  • addr_dest: 目标地址。

设置接收地址后,通信只能与特定设备进行,并且其他对等方将被过滤掉。 过滤由接收方强制执行。 如果未设置 SER_RS485_ADDR_RECV,则将清除接收地址。

注意:并非所有支持 RS485 的设备都支持多点寻址。

6. 参考