树莓派GPIO引脚功能与UART映射:BCM与wPi编号、UART0/UART1、硬件流控

说实话,刚接触树莓派GPIO的人,十有八九会被那两套编号搞晕。我当年第一次点亮LED,照着教程写GPIO 17,结果怎么都不亮——后来才发现教程用的是wPi编号,而我写的是BCM编号。嗯,这种坑踩过一次就记住了。

这一章,咱们就把GPIO的引脚功能、UART映射、编号体系彻底理清楚。你搞懂了这些,后面用pyserial跟工业设备通信才不会跑偏。

BCM编号 vs wPi编号:两套江湖规矩

树莓派40针排针上,每一针都有物理位置编号(Physical Pin Number),从1到40。但软件层面,大家用的却是另外两套编号:

编号体系 来源 特点 常用库
BCM编号 Broadcom SoC内部GPIO号 与芯片引脚直接对应,跨板卡一致 RPi.GPIO、pigpio、wiringPi(BCM模式)
wPi编号 Wiring Pi库自定义 按排针物理顺序重新编号,方便记忆 wiringPi(已停更,但存量代码多)
Physical编号 排针物理位置 1~40,最直观,但软件不直接使用 仅用于参考

我个人习惯用BCM编号。为什么?因为它是芯片原厂的编号,换板子(比如从Pi 3B+换到Pi 4B)时,BCM编号基本不变。wPi编号虽然好记,但wiringPi库已经停更了,新项目再用它,有点给自己挖坑的意思。

核心原则:新项目一律用BCM编号。如果你接手旧代码看到wPi编号,先确认它用的是哪个库,再决定是否迁移。

UART0与UART1:两个串口的恩怨

树莓派上有两个硬件UART:UART0(也叫PL011)和UART1(也叫mini UART)。它们不是平级关系,性能差距挺大。

特性 UART0 (PL011) UART1 (mini UART)
硬件基础 独立UART外设(ARM PL011) 基于BCM2835 AUX模块
波特率精度 高,支持非标准波特率 低,依赖VPU时钟频率
硬件流控 支持(RTS/CTS) 不支持
FIFO深度 16字节 8字节
中断支持 完整 有限
默认用途 蓝牙(Pi 3B+/4B) GPIO 14/15 串口终端

你想想看,如果跟工业设备通信,波特率要求115200甚至更高,数据量又大——用UART1就很容易丢数据。我在一个自动化产线项目里就吃过这个亏:设备偶尔丢包,排查了两天才发现是mini UART的FIFO太小,加上VPU频率波动导致波特率漂移。

避坑指南:工业通信场景,优先使用UART0。如果UART0被蓝牙占用,可以通过dtoverlay=disable-bt释放出来。别图省事直接用UART1,除非你只接调试终端。

GPIO引脚与UART映射关系

树莓派40针排针上,UART信号映射到固定的GPIO引脚。以BCM编号为例:

UART实例 TX (BCM) RX (BCM) RTS (BCM) CTS (BCM) 物理引脚
UART0 GPIO 14 GPIO 15 GPIO 17 GPIO 16 8/10/11/12
UART1 GPIO 14 GPIO 15 不支持 不支持 8/10
UART0 (备用) GPIO 0 GPIO 1 GPIO 2 GPIO 3 27/28/3/5

注意,UART0和UART1的TX/RX默认都映射到GPIO 14/15。这意味着它们不能同时使用同一组引脚。你需要在/boot/config.txt里通过设备树覆盖来切换。

小技巧:如果你需要两个串口同时工作,可以把UART0映射到GPIO 0/1(物理引脚27/28),UART1保留在GPIO 14/15。这样就能同时使用两个硬件UART了。

硬件流控:什么时候必须用?

硬件流控(RTS/CTS)说白了就是让设备之间互相说“慢点,我还没处理完”。它用两根额外的信号线来实现:

  • RTS(Request To Send):发送方告诉接收方“我要发数据了,你准备好没?”
  • CTS(Clear To Send):接收方回答“准备好了,发吧”

我在项目中遇到过这样的情况:用115200波特率跟PLC通信,数据包长度256字节,没有流控。结果PLC那边处理不过来,缓冲区溢出,数据就丢了。后来加上RTS/CTS硬件流控,问题立刻解决。

什么时候必须用硬件流控?

  • 波特率高于57600
  • 数据包长度超过64字节
  • 通信双方处理速度不匹配(比如树莓派快,设备慢)
  • 半双工转全双工场景

如果只是接个调试终端,或者波特率9600、数据量很小,软件流控(XON/XOFF)也够用。但工业场景,我建议直接上硬件流控,省心。

知识结构总览

下面这张图把本章的核心逻辑串起来了。你一看就明白:编号体系、UART选择、引脚映射、流控决策,它们之间的关系。

树莓派GPIO与UART知识结构图 树莓派GPIO与UART知识结构 GPIO与UART 编号体系 UART实例 硬件流控 BCM编号 wPi编号 Physical编号 UART0 (PL011) UART1 (mini) RTS/CTS XON/XOFF 工业通信建议:BCM编号 + UART0 + 硬件流控 避免使用UART1进行高速/大数据量通信 核心逻辑:编号选对 → UART选对 → 流控选对 三者缺一不可,否则通信不稳定

实战:查看当前UART映射状态

在动手接线之前,先确认你的树莓派当前UART映射状态。打开终端,运行:

# 查看UART设备
ls -l /dev/serial*

# 查看GPIO功能复用状态
raspi-gpio get 14-15

# 查看设备树覆盖
dtoverlay -a | grep uart

输出示例:

/dev/serial0 -> ttyAMA0
/dev/serial1 -> ttyS0

GPIO 14: level=1 func=ALT0
GPIO 15: level=1 func=ALT0

这里serial0通常指向UART0(ttyAMA0),serial1指向UART1(ttyS0)。如果serial0指向ttyS0,说明UART0被蓝牙占用了,你需要释放它。

快速检查:运行ls -l /dev/serial*,看serial0指向谁。指向ttyAMA0就是UART0,指向ttyS0就是UART1。这个命令我几乎每次调试都会先用一遍。

释放UART0给串口使用

如果你用的是Pi 3B+或4B,UART0默认分配给蓝牙。想把它还给串口,编辑/boot/config.txt:

# 禁用蓝牙,释放UART0
dtoverlay=disable-bt

# 或者只禁用蓝牙的UART,保留蓝牙其他功能
dtoverlay=miniuart-bt

然后重启:

sudo reboot

重启后再看/dev/serial*,serial0应该指向ttyAMA0了。

注意:禁用蓝牙后,树莓派的蓝牙功能就没了。如果你需要蓝牙,用miniuart-bt方案——把UART1给蓝牙用,UART0留给串口。但UART1性能差,蓝牙通信可能受影响。我一般直接禁用蓝牙,反正工业场景很少用蓝牙。

小结

这一章的内容,说白了就是三件事:

  • 编号用BCM,别用wPi,省得以后踩坑
  • UART用0,别用1,除非你只接调试终端
  • 流控用硬件,别省那两根线,工业通信稳定第一