4. UARTE外设驱动与板级串口适配

nRF54 系列把传统 UART 升级为 UARTE(UART with EasyDMA),收发数据不再由 CPU 逐字节搬运,而是由 EasyDMA 在 RAM 与外设之间直接搬运。理解这一点,是写好串口驱动和做好板级适配的前提:配置对象从“寄存器+中断”变成了“寄存器+EasyDMA 通道+缓冲区”,调试时也要同时关注外设状态和内存搬运状态。

一、UARTE 的异步收发与 EasyDMA 通道分配

UARTE 的收发都通过 EasyDMA 完成。发送时,CPU 把待发数据的地址和长度写入 TXD.PTR 与 TXD.MAXCNT,再触发 TASKS_STARTTX,EasyDMA 自动从 RAM 读取并送入发送移位器;接收时,把接收缓冲区地址和容量写入 RXD.PTR 与 RXD.MAXCNT,触发 TASKS_STARTRX 后,硬件把收到的字节写入缓冲区,直到缓冲区满或收到结束条件,产生 EVENTS_ENDRX。

关键约束是:EasyDMA 只能访问 RAM,不能直接指向 Flash 中的常量字符串。若要把常量字符串发出去,必须先拷贝到 RAM 缓冲区。此外,缓冲区在传输期间不能被移动或释放,否则 DMA 会读到错误地址。nRF54 的 UARTE 实例通常有独立的 DMA 资源,多个 UARTE 同时工作时不需要手工“分配通道号”,但每个实例的 TXD/RXD 缓冲区必须各自独立,不能复用同一块内存。

异步收发的典型做法是“双缓冲+回调”:准备两块接收缓冲区,一块正在被 DMA 写入时,另一块已满并交给协议层解析;在 ENDRX 中断里切换指针并重新启动接收。这样即使上层解析稍慢,也不会丢字节。发送侧则常用“发送完成中断 EVENTS_TXDRDY 或 EVENTS_ENDTX”来释放缓冲区并触发下一包。

二、流控、波特率与引脚映射

当对端可能连续发送、而本端处理不及时,应启用硬件流控 RTS/CTS。UARTE 的 CONFIG 寄存器中使能 HWFC 后,RTS 由硬件根据接收缓冲区余量自动拉低/拉高,CTS 则决定本端是否继续发送。流控能有效避免溢出,但会多占用两个引脚,且要求对端同样支持。

波特率由 BAUDRATE 寄存器设置,nRF54 支持从 1200 到 1 Mbps 的常用档位。选择时要同时考虑对端能力和时钟精度:高速率下对时钟误差更敏感,若使用内部 RC 振荡器,建议把波特率限制在较低档,或改用外部晶振。引脚映射通过 PSEL.TXD、PSEL.RXD、PSEL.RTS、PSEL.CTS 指定,必须与板级实际走线一致;nRF54 的 GPIO 可灵活映射,但要注意某些引脚有默认复用功能,配置前应确认没有被其他外设占用。

// 以 nRF Connect SDK 为例的 UARTE 设备树片段(示意)
&uart30 {
    status = "okay";
    current-speed = <115200>;
    hw-flow-control;
    pinctrl-0 = <&uart30_default>;
    pinctrl-1 = <&uart30_sleep>;
};
&uart30_default {
    group1 {
        psels = <NRF_PSEL(UART_TX, 1, 8)>,
                <NRF_PSEL(UART_RX, 1, 9)>,
                <NRF_PSEL(UART_RTS, 1, 10)>,
                <NRF_PSEL(UART_CTS, 1, 11)>;
    };
};

上面示例把 TX/RX/RTS/CTS 分别映射到 P1.08~P1.11,波特率 115200 并启用流控。实际项目中这些值必须与原理图核对,不能照抄。

三、RS232/RS485 电平转换电路适配

nRF54 的 UARTE 引脚是 3.3 V(或 1.8 V)TTL/CMOS 电平,不能直接接 RS232 的 ±12 V,也不能直接接 RS485 的差分总线。RS232 方向需要电平转换芯片,如 MAX3232 类器件,把 TTL 的 TX/RX 转成 RS232 电平;RS485 方向需要差分收发器,如 MAX485/SP3485 类器件,把 TTL 的 TX/RX 转成 A/B 差分对,并由 DE/RE 引脚控制收发方向。

RS485 半双工适配的关键是方向控制:发送前拉高 DE 并释放 RE,发送完成后(以 ENDTX 或发送移位器空为标志)再拉低 DE,切回接收。若切换过早,最后一个字节会被截断;切换过晚,则会占用总线、影响对端应答。工程上常在发送完成中断里延时几个比特时间再切换,或使用带自动方向控制的收发器。总线两端还需 120 Ω 终端电阻,A/B 线不能接反。

四、回环测试与结果判读

板级适配完成后,最直接的验证是回环测试。把 TX 与 RX 短接(或经收发器自环),发送已知数据,检查接收缓冲区是否逐字节一致。测试应覆盖:单字节、整缓冲区边界、超过缓冲区长度、流控开启/关闭、不同波特率。若回环失败,先确认引脚映射和电平方向,再检查 DMA 缓冲区是否在 RAM、是否被复用,最后核对波特率和时钟源。

UARTE 异步收发与板级适配信号链 nRF54 UARTE TXD.PTR / MAXCNT RXD.PTR / MAXCNT EasyDMA 搬运 RAM 缓冲区 TX Buffer RX Buffer A / B 双缓冲切换,避免丢字节 电平转换 RS232: MAX3232 RS485: MAX485 DE/RE 方向控制 TX RX 总线 / 连接器 RS232: TXD/RXD/GND RS485: A / B / GND 120Ω 终端电阻 差分/电平 回环测试:TX 短接 RX,逐字节比对 关键检查:缓冲区必须在 RAM、传输期间不可移动;流控引脚与对端一致;RS485 方向切换在发送完成后进行

回环测试通过后,还应做一次“真实对端”验证:用 PC 串口助手或另一块板子,在 115200、启用流控的条件下连续发送 1 KB 随机数据,检查接收计数与校验和是否一致。若出现偶发错误,优先怀疑波特率误差、地线干扰或 RS485 方向切换时机,而不是先改驱动逻辑。

板级适配的核对顺序建议固定为:原理图引脚 → 设备树 pinctrl → 电平转换芯片供电与使能 → 总线终端 → 回环测试 → 真实对端测试。按这个顺序排查,能避免在软件层反复修改却找不到根因。