瑞芯微 RK3506 平台嵌入式 Linux RS485 串行通讯驱动开发
一、UART与RS485的核心关系与引脚差异
先从本质上厘清UART和RS485二者的定位与区别。
1.1 本质关系
- UART(通用异步收发传输器):是芯片级的串行通讯协议与外设控制器,工作在TTL电平逻辑层面,定义了异步串行通讯的帧格式(起始位、数据位、校验位、停止位),是MCU/MPU与外设之间短距离(厘米级到米级)的芯片间通讯接口。
- RS485:是电气物理层标准,定义了差分传输的电气特性,解决了UART TTL电平长距离传输抗干扰差、无法多节点组网的问题。工业场景中,RS485通讯的本质是「UART控制器 + RS485收发芯片」的组合实现,用UART完成串行数据的编解码,用RS485芯片完成TTL电平到差分总线信号的转换与传输。
1.2 核心引脚差异
标准UART引脚
基础UART仅需2根核心引脚,硬件流控场景扩展为4根:
| UART引脚 | 功能说明 |
|---|---|
| TXD | 发送数据,TTL电平,MCU向外设发送数据 |
| RXD | 接收数据,TTL电平,MCU接收外设发送的数据 |
| RTS | 请求发送,硬件流控引脚,MCU向外设发送发送请求 |
| CTS | 清除发送,硬件流控引脚,外设向MCU回复允许发送 |
RS485收发芯片引脚(以本文SIT3485E/MAX485为例)
RS485半双工收发芯片核心引脚分为主控侧和总线侧:
| 芯片引脚 | 功能说明 | 与MCU UART的连接 |
|---|---|---|
| RO | 接收输出,TTL电平,芯片从总线收到数据后从此引脚输出 | 接MCU UART的RXD引脚 |
| DI | 发送输入,TTL电平,MCU要发送的数据从此引脚输入芯片 | 接MCU UART的TXD引脚 |
| RE | 接收使能,低电平有效,有效时芯片处于接收模式 | 接MCU UART的RTS引脚 |
| DE | 发送使能,高电平有效,有效时芯片处于发送模式 | 与RE短接,共同接MCU UART的RTS引脚 |
| A/B | 差分总线引脚,RS485总线的正负端,负责长距离差分信号传输 | 接RS485总线端子,与从设备A-A、B-B对接 |
关键设计:将RE与DE短接,用单个RTS引脚即可实现RS485半双工的收发方向自动控制。当RTS输出低电平时,RE有效、DE无效,芯片进入接收模式;当RTS输出高电平时,DE有效、RE无效,芯片进入发送模式。Linux串口驱动可自动完成RTS电平的切换,无需应用层干预。
二、UART的中断模式与DMA模式详解与选型
RK3506的UART控制器基于Synopsys DW APB UART IP核,支持中断驱动模式和DMA驱动模式两种数据收发方式,二者的适用场景与性能差异极大,开发时需按需选择。
2.1 中断驱动模式
工作原理
中断模式是UART最基础的工作模式:内核配置UART的FIFO触发阈值,当接收FIFO中的数据量达到阈值、或发送FIFO为空时,UART控制器向CPU触发硬件中断;CPU响应中断后,在中断处理函数中完成数据的读写操作。
优缺点
- 优点:实现简单,资源占用少,无需占用DMA通道,驱动适配门槛低;
- 缺点:高波特率、大数据量场景下,中断触发频率极高,会大幅占用CPU资源,甚至出现中断丢失、数据丢包的问题。
适用场景
波特率≤115200、数据收发为问答式(如Modbus RTU)、小数据量的常规工业控制场景,中断模式完全可以满足需求,是默认的首选方案。
2.2 DMA驱动模式
工作原理
DMA(直接内存访问)模式下,UART的收发数据搬运完全由DMA控制器完成,无需CPU介入:内核提前配置好DMA的内存地址、传输长度与通道,UART接收数据时,DMA自动将FIFO中的数据搬运到内存缓冲区;发送数据时,DMA自动将内存中的数据搬运到UART发送FIFO。只有当整块数据传输完成时,DMA才会向CPU触发一次中断。
优缺点
- 优点:高波特率、大数据量场景下CPU占用率极低,数据传输稳定,几乎不会出现丢包,可支持最高波特率的持续数据流传输;
- 缺点:需要占用专属的DMA通道,配置相对复杂,小数据量场景下,DMA的初始化与启动开销反而会导致传输效率低于中断模式。
适用场景
波特率≥230400、持续大数据量传输(如串口透传、高速数据采集)、对CPU占用率敏感的场景,必须选择DMA模式。
2.3 选型总结
| 场景 | 推荐模式 |
|---|---|
| 常规Modbus RTU、9600/115200波特率、问答式通讯 | 中断模式 |
| 高速透传、230400及以上波特率、持续数据流 | DMA模式 |
| DMA通道被其他外设(如SPI、I2S)占满 | 中断模式 |
RK3506的UART设备树中,若保留
dmas属性,驱动会优先启用DMA模式;若删除dmas属性,驱动自动切换为中断模式。
三、从硬件原理图到设备树:RS485链路的全映射
本节基于RK3506 EVB开发板的实际RS485电路,完整讲解硬件原理图的设计逻辑,以及如何对应到设备树配置,最终实现硬件到Linux系统的适配。


3.1 RS485硬件原理图详解
开发板的RS485电路基于UART3扩展,核心芯片为SIT3485E半双工RS485收发器,电路分为主控对接电路、RS485总线电路、电源与保护电路三部分。
3.1.1 主控对接电路(RK3506与SIT3485E的连接)
这部分是硬件与设备树适配的核心,对应原理图的信号链路如下:
- UART3_TX:RK3506的GPIO1_B2引脚,复用为UART3的发送功能,经过22R限流电阻后,接入SIT3485E的DI引脚(4脚),负责将MCU的串行数据发送到RS485芯片。
- UART3_RX:RK3506的GPIO1_B3引脚,复用为UART3的接收功能,经过22R限流电阻后,接入SIT3485E的RO引脚(1脚),负责接收RS485芯片从总线采集的数据。
- UART3_RTSN:RK3506的GPIO1_B1引脚,复用为UART3的RTS流控功能,经过0R电阻后,同时接入SIT3485E的RE(2脚)和DE(3脚),作为RS485收发方向的控制引脚,这是RS485半双工通讯的核心。
- UART3_CTSN:原理图中为NC/0R未连接,本次设计未使用硬件流控的CTS引脚。
3.1.2 RS485总线电路
- 差分总线引脚A/B:SIT3485E的6脚(A)、7脚(B)为RS485差分总线输出,通过端子CON9301引出,与外部从设备实现A-A、B-B对接。
- 偏置与匹配电路:
- 3.3K上拉/下拉电阻:为总线提供固定偏置电平,避免总线空闲时电平浮动导致的乱码;
- 120R终端电阻:通过跳线可选焊接,RS485总线规范要求,总线两端的节点必须接入120R终端电阻,用于阻抗匹配,减少信号反射,中间节点无需接入;
- 56pF滤波电容:滤除总线上的高频干扰,提升EMC性能。
- ESD保护电路:TVS管ED9301并联在A/B总线上,用于静电和浪涌保护,提升工业场景的可靠性。
3.1.3 电源与辅助电路
SIT3485E采用3.3V供电,电源端并联100nF去耦电容,滤除电源噪声;肖特基二极管D9300用于防反接保护,避免电源接反损坏芯片。
3.2 设备树配置详解与硬件的对应关系
RK3506平台的设备树分为核心芯片级dtsi和板级dts两部分,前者定义了UART控制器的通用参数,后者完成板级硬件的适配与使能。
3.2.1 芯片级dtsi:UART3控制器的基础定义
uart3: serial@ff0d0000 {
compatible = "rockchip,rk3506-uart", "snps,dw-apb-uart";
reg = <0xff0d0000 0x100>;
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
reg-io-width = <4>;
dmas = <&dmac0 10 0xff2880ac 0x00300010 0x0 0x0>,
<&dmac0 11 0xff2880ac 0x00c00040 0x0 0x0>;
clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>;
clock-names = "baudclk", "apb_pclk";
status = "disabled";
};
每个参数与硬件的对应关系:
compatible:兼容字符串,用于和内核中的DW APB UART驱动匹配,是驱动探测设备的核心标识;reg:UART3控制器的寄存器物理基地址0xff0d0000和地址长度0x100,CPU通过该地址访问UART的配置寄存器;interrupts:UART3的中断号37,UART的收发、错误事件均通过该中断上报CPU;reg-shift/reg-io-width:定义寄存器的寻址方式,DW UART IP为32位寄存器,4字节对齐,因此配置为reg-shift=<2>、reg-io-width=<4>;dmas:定义UART3收发对应的DMA通道,驱动通过该参数启用DMA模式;clocks:定义UART3的波特率时钟和APB总线时钟,驱动通过该时钟计算波特率分频系数;status = "disabled":芯片级dtsi默认关闭该外设,需要在板级dts中使能。
3.2.2 板级dts:RS485功能的适配与使能
板级dts中需要完成引脚复用配置、RS485功能使能、外设启用三个核心工作,对应配置如下:
&uart3 {
pinctrl-names = "default";
pinctrl-0 = <&rm_io26_uart3_tx &rm_io25_uart3_rx &rm_io24_uart3_rtsn &rm_io29_uart3_ctsn>;
linux,rs485-enabled-at-boot-time; /* 核心:启用RS485模式 */
status = "okay";
};
关键配置的硬件对应逻辑:
-
pinctrl引脚复用配置
pinctrl-0中的四个节点,分别将对应的GPIO引脚复用为UART3的TX、RX、RTSN、CTSN功能,对应原理图中的GPIO1_B1(RTSN)、GPIO1_B2(TX)、GPIO1_B3(RX)引脚。只有完成引脚复用配置,UART控制器才能接管这些GPIO,否则引脚只能作为普通GPIO使用。 -
RS485模式核心配置
linux,rs485-enabled-at-boot-time是Linux内核串口驱动标准的RS485使能属性,该属性会告诉驱动:- 该UART工作在RS485半双工模式;
- 启动时自动使能RS485功能;
- 自动使用RTS引脚完成收发方向的电平控制,发送时拉高RTS,接收时拉低RTS,完全匹配我们的硬件设计。
补充配置:若硬件设计中RTS引脚的有效电平为低,需要额外添加
linux,rs485-rts-active-low属性,调整驱动的电平控制逻辑。 -
外设使能
status = "okay"将UART3控制器从默认关闭状态改为启用状态,内核启动时会加载驱动并探测该设备。
3.3 从物理硬件到/dev/tty设备的完整链路
很多开发者好奇,一个物理的RS485接口,是如何变成Linux系统中可操作的/dev/ttySx设备的,完整流程分为5步:
- 硬件链路就绪:RK3506的UART3控制器通过GPIO连接RS485收发芯片,完成硬件物理链路的搭建。
- 设备树信息上报:内核启动时,解析设备树中的uart3节点,获取该外设的寄存器地址、中断、时钟、引脚复用、RS485配置等全部硬件信息。
- 驱动匹配与探测:内核总线驱动遍历设备树节点,uart3的
compatible属性与内核中的dw-apb-uart驱动匹配成功,驱动执行probe函数,完成设备的探测与初始化。 - 驱动初始化与配置:
- 完成寄存器地址映射、中断申请、时钟使能;
- 配置pinctrl,完成GPIO引脚的功能复用;
- 解析RS485属性,配置UART为RS485模式,设置RTS方向控制逻辑;
- 根据dmas配置,初始化DMA通道或启用中断模式;
- 向内核tty子系统注册串行设备。
- 设备节点生成:内核的udev服务根据tty子系统上报的设备信息,在/dev目录下创建对应的设备节点
/dev/ttyS3(RK平台UART编号与ttyS编号可以在uboot设备树配置,默认一一对应,uart0对应ttyS0,uart3对应ttyS3),应用层即可通过该节点访问RS485接口。
四、Linux系统下RS485通讯的验证与调试
完成硬件与设备树配置后,我们需要通过以下步骤,逐步验证RS485链路的完整性与可用性。
4.1 基础验证:设备与驱动是否正常加载
-
确认tty设备节点存在
执行以下命令,查看系统中的串口设备,确认/dev/ttyS3存在:ls /dev/ttyS*若输出中包含
ttyS3,说明设备已成功注册到tty子系统。 -
查看内核驱动探测日志
执行以下命令,查看UART3的驱动加载日志,确认probe成功:dmesg | grep ttyS3 # 或通过寄存器地址过滤 dmesg | grep ff0d0000.serial正常输出示例:
serial8250.0: ttyS3 at MMIO 0xff0d0000 (irq = 37, base_baud = 115200) is a 16550A若出现该日志,说明驱动已成功匹配并初始化UART3控制器。
-
确认引脚复用配置正确
执行以下命令,查看引脚复用状态,确认对应GPIO已复用为UART3功能:cat /sys/kernel/debug/pinctrl/pinctrl-rockchip-pinctrl/pinmux-pins | grep uart3若输出中显示对应引脚的mux function为uart3,说明引脚复用配置成功。
4.2 功能验证:RS485自发自收回环测试
回环测试是验证RS485收发功能最直接的方式,无需额外从设备。
- 硬件准备:用导线将RS485端子的A和B引脚短接,实现自发自收的硬件回环。
- 工具准备:安装串口调试工具,推荐使用
microcom、minicom,或直接使用系统自带的stty、cat、echo命令。 - 测试步骤:
- 第一步,配置串口参数(115200波特率、8数据位、1停止位、无校验、原始模式):
stty -F /dev/ttyS3 115200 cs8 -cstopb -parenb raw - 第二步,打开两个终端窗口,第一个终端执行接收命令,监听串口数据:
cat /dev/ttyS3 - 第三步,第二个终端执行发送命令,向串口写入测试数据:
echo "RK3506 RS485 Test Success" > /dev/ttyS3
- 第一步,配置串口参数(115200波特率、8数据位、1停止位、无校验、原始模式):
- 结果判断:若接收终端成功打印出发送的测试字符串,说明RS485的收发功能、驱动方向控制、硬件链路完全正常。
4.3 实际场景验证:总线双向通讯测试
- 硬件准备:准备一个RS485从设备(如Modbus RTU传感器、另一台RS485开发板),将开发板与从设备的A-A、B-B对接,总线两端的设备接入120R终端电阻。
- 软件测试:使用
modpoll(Modbus主站工具)、minicom等工具,与从设备进行双向通讯,确认数据收发正常,无丢包、乱码问题。
4.4 常见问题排查
- 无法收到数据:优先检查RTS引脚的电平控制是否正常,用示波器查看发送时RTS引脚是否有电平跳变,A/B总线是否有差分信号;其次确认引脚复用是否正确,RS485属性是否添加。
- 数据乱码:优先确认收发双方的波特率、数据位、停止位、校验位是否完全匹配;其次检查总线偏置电阻、终端电阻是否正确焊接,是否存在信号干扰。
- 只能发送不能接收:检查RE/DE引脚的控制逻辑是否与驱动匹配,确认RTS引脚的有效电平是否正确,必要时添加
linux,rs485-rts-active-low属性调整电平逻辑。

浙公网安备 33010602011771号