瑞芯微 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系统的适配。

image
image

3.1 RS485硬件原理图详解

开发板的RS485电路基于UART3扩展,核心芯片为SIT3485E半双工RS485收发器,电路分为主控对接电路RS485总线电路电源与保护电路三部分。

3.1.1 主控对接电路(RK3506与SIT3485E的连接)

这部分是硬件与设备树适配的核心,对应原理图的信号链路如下:

  1. UART3_TX:RK3506的GPIO1_B2引脚,复用为UART3的发送功能,经过22R限流电阻后,接入SIT3485E的DI引脚(4脚),负责将MCU的串行数据发送到RS485芯片。
  2. UART3_RX:RK3506的GPIO1_B3引脚,复用为UART3的接收功能,经过22R限流电阻后,接入SIT3485E的RO引脚(1脚),负责接收RS485芯片从总线采集的数据。
  3. UART3_RTSN:RK3506的GPIO1_B1引脚,复用为UART3的RTS流控功能,经过0R电阻后,同时接入SIT3485E的RE(2脚)和DE(3脚),作为RS485收发方向的控制引脚,这是RS485半双工通讯的核心。
  4. UART3_CTSN:原理图中为NC/0R未连接,本次设计未使用硬件流控的CTS引脚。

3.1.2 RS485总线电路

  1. 差分总线引脚A/B:SIT3485E的6脚(A)、7脚(B)为RS485差分总线输出,通过端子CON9301引出,与外部从设备实现A-A、B-B对接。
  2. 偏置与匹配电路
    • 3.3K上拉/下拉电阻:为总线提供固定偏置电平,避免总线空闲时电平浮动导致的乱码;
    • 120R终端电阻:通过跳线可选焊接,RS485总线规范要求,总线两端的节点必须接入120R终端电阻,用于阻抗匹配,减少信号反射,中间节点无需接入;
    • 56pF滤波电容:滤除总线上的高频干扰,提升EMC性能。
  3. 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";
};

关键配置的硬件对应逻辑:

  1. pinctrl引脚复用配置
    pinctrl-0中的四个节点,分别将对应的GPIO引脚复用为UART3的TX、RX、RTSN、CTSN功能,对应原理图中的GPIO1_B1(RTSN)、GPIO1_B2(TX)、GPIO1_B3(RX)引脚。只有完成引脚复用配置,UART控制器才能接管这些GPIO,否则引脚只能作为普通GPIO使用。

  2. RS485模式核心配置
    linux,rs485-enabled-at-boot-time是Linux内核串口驱动标准的RS485使能属性,该属性会告诉驱动:

    • 该UART工作在RS485半双工模式;
    • 启动时自动使能RS485功能;
    • 自动使用RTS引脚完成收发方向的电平控制,发送时拉高RTS,接收时拉低RTS,完全匹配我们的硬件设计。

    补充配置:若硬件设计中RTS引脚的有效电平为低,需要额外添加linux,rs485-rts-active-low属性,调整驱动的电平控制逻辑。

  3. 外设使能
    status = "okay"将UART3控制器从默认关闭状态改为启用状态,内核启动时会加载驱动并探测该设备。

3.3 从物理硬件到/dev/tty设备的完整链路

很多开发者好奇,一个物理的RS485接口,是如何变成Linux系统中可操作的/dev/ttySx设备的,完整流程分为5步:

  1. 硬件链路就绪:RK3506的UART3控制器通过GPIO连接RS485收发芯片,完成硬件物理链路的搭建。
  2. 设备树信息上报:内核启动时,解析设备树中的uart3节点,获取该外设的寄存器地址、中断、时钟、引脚复用、RS485配置等全部硬件信息。
  3. 驱动匹配与探测:内核总线驱动遍历设备树节点,uart3的compatible属性与内核中的dw-apb-uart驱动匹配成功,驱动执行probe函数,完成设备的探测与初始化。
  4. 驱动初始化与配置
    • 完成寄存器地址映射、中断申请、时钟使能;
    • 配置pinctrl,完成GPIO引脚的功能复用;
    • 解析RS485属性,配置UART为RS485模式,设置RTS方向控制逻辑;
    • 根据dmas配置,初始化DMA通道或启用中断模式;
    • 向内核tty子系统注册串行设备。
  5. 设备节点生成:内核的udev服务根据tty子系统上报的设备信息,在/dev目录下创建对应的设备节点/dev/ttyS3(RK平台UART编号与ttyS编号可以在uboot设备树配置,默认一一对应,uart0对应ttyS0,uart3对应ttyS3),应用层即可通过该节点访问RS485接口。

四、Linux系统下RS485通讯的验证与调试

完成硬件与设备树配置后,我们需要通过以下步骤,逐步验证RS485链路的完整性与可用性。

4.1 基础验证:设备与驱动是否正常加载

  1. 确认tty设备节点存在
    执行以下命令,查看系统中的串口设备,确认/dev/ttyS3存在:

    ls /dev/ttyS*
    

    若输出中包含ttyS3,说明设备已成功注册到tty子系统。

  2. 查看内核驱动探测日志
    执行以下命令,查看UART3的驱动加载日志,确认probe成功:

    dmesg | grep ttyS3
    # 或通过寄存器地址过滤
    dmesg | grep ff0d0000.serial
    

    正常输出示例:

    serial8250.0: ttyS3 at MMIO 0xff0d0000 (irq = 37, base_baud = 115200) is a 16550A
    

    若出现该日志,说明驱动已成功匹配并初始化UART3控制器。

  3. 确认引脚复用配置正确
    执行以下命令,查看引脚复用状态,确认对应GPIO已复用为UART3功能:

    cat /sys/kernel/debug/pinctrl/pinctrl-rockchip-pinctrl/pinmux-pins | grep uart3
    

    若输出中显示对应引脚的mux function为uart3,说明引脚复用配置成功。

4.2 功能验证:RS485自发自收回环测试

回环测试是验证RS485收发功能最直接的方式,无需额外从设备。

  1. 硬件准备:用导线将RS485端子的A和B引脚短接,实现自发自收的硬件回环。
  2. 工具准备:安装串口调试工具,推荐使用microcomminicom,或直接使用系统自带的sttycatecho命令。
  3. 测试步骤
    • 第一步,配置串口参数(115200波特率、8数据位、1停止位、无校验、原始模式):
      stty -F /dev/ttyS3 115200 cs8 -cstopb -parenb raw
      
    • 第二步,打开两个终端窗口,第一个终端执行接收命令,监听串口数据:
      cat /dev/ttyS3
      
    • 第三步,第二个终端执行发送命令,向串口写入测试数据:
      echo "RK3506 RS485 Test Success" > /dev/ttyS3
      
  4. 结果判断:若接收终端成功打印出发送的测试字符串,说明RS485的收发功能、驱动方向控制、硬件链路完全正常。

4.3 实际场景验证:总线双向通讯测试

  1. 硬件准备:准备一个RS485从设备(如Modbus RTU传感器、另一台RS485开发板),将开发板与从设备的A-A、B-B对接,总线两端的设备接入120R终端电阻。
  2. 软件测试:使用modpoll(Modbus主站工具)、minicom等工具,与从设备进行双向通讯,确认数据收发正常,无丢包、乱码问题。

4.4 常见问题排查

  1. 无法收到数据:优先检查RTS引脚的电平控制是否正常,用示波器查看发送时RTS引脚是否有电平跳变,A/B总线是否有差分信号;其次确认引脚复用是否正确,RS485属性是否添加。
  2. 数据乱码:优先确认收发双方的波特率、数据位、停止位、校验位是否完全匹配;其次检查总线偏置电阻、终端电阻是否正确焊接,是否存在信号干扰。
  3. 只能发送不能接收:检查RE/DE引脚的控制逻辑是否与驱动匹配,确认RTS引脚的有效电平是否正确,必要时添加linux,rs485-rts-active-low属性调整电平逻辑。
posted @ 2026-03-17 17:46  Asp1rant  阅读(23)  评论(0)    收藏  举报