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 工作的设备驱动程序都应在
struct uart_port
中实现rs485_config
回调并提供rs485_supported
。串行核心调用rs485_config
以响应 TIOCSRS485 ioctl(见下文)执行特定于设备的部分。rs485_config
回调接收指向已清理的struct serial_rs485
的指针。在调用rs485_config
之前,使用rs485_supported
清理用户空间提供的struct serial_rs485
,该值指示驱动程序为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 的设备都支持多点寻址。