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_rs485
,rs485_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
已弃用,请改用 padding0 和 padding1。 请勿与 addr_recv 和 addr_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 的设备都支持多点寻址。