做树莓派开发,串口是躲不开的硬骨头。不管你是想接一块GPS模块、给ESP32小车发控制指令,还是打算用STM32做底层控制、树莓派做上层决策,最终都要面对/dev目录底下那一排乱糟糟的设备名:ttyAMA0、ttyS0、ttyUSB0、ttyACM0……刚上手的人十有八九要在这里卡住——明明在排针上接了 TTL 电平的 TX、RX、GND,为什么数据就是不出来?更麻烦的是,树莓派3B/4B上还藏着一个“蓝牙抢串口”的历史问题,很多人折腾到半夜才发现自己一直在跟一个被系统占用的端口较劲。
这篇是“树莓派串口完全指南”系列的第一篇,把“各串口”这件事彻底讲清楚:树莓派内部到底有几个UART控制器,各自有什么脾气,GPIO14/15上默认是哪一个,蓝牙是怎么插一脚的,以及树莓派5上串口体系为什么变了。顺便把权限配置、回环测试、USB转串口这些高频场景也一并覆盖。适合刚拿到板子准备做UART通信的小白,也适合被串口名折腾过但仍没理清头绪的开发者。
1. 树莓派上的串口资源:从SoC到40pin排针
1.1 两个串口控制器:PL011与mini UART
树莓派主芯片里并不是只有一个串口,而是至少有两套UART控制器在运作,分别叫PL011和mini UART。这个设计从树莓派初代一路延续到4B,直到树莓派5才被彻底改头换面。
PL011 是ARM体系里经典的PrimeCell UART IP,属于“正规军”。它拥有独立的时钟源,波特率精度高,FIFO更充裕,支持硬件流控(RTS/CTS),中断和DMA机制也完整。你可以把它理解成一条高标准的高速公路,无论是跑 9600 波特率还是 115200 波特率,数据都能稳稳定时送达。
mini UART 则完全是另一路画风,它挂在AUX外设总线上,是博通为了省面积和成本塞进去的精简UART。它的时钟来源于GPU核心频率,核心频率一变,波特率就跟着飘。迷你串口的FIFO小,没有硬件流控,DMA支持也残缺,更像一条“乡间小路”,平时低速跑跑还行,一旦遇到CPU负载波动或者高波特率传输,就容易丢字节、出乱码。很多人在树莓派3之后觉得串口不如以前稳定,原因基本都出在这里——你很可能在用 mini UART,而不是 PL011。
我把这两个控制器的区别整理成了下面这张表,方便你对照排查:
| 对比项 | PL011 (ttyAMA0) | mini UART (ttyS0) |
|---|---|---|
| 时钟来源 | 独立UART时钟 | 跟随GPU核心频率 |
| 波特率稳定性 | 高 | 低,负载高时漂移 |
| 硬件流控 | 支持RTS/CTS | 不支持 |
| FIFO大小 | 较大 | 较小 |
| DMA支持 | 完整 | 有限/不可靠 |
| 推荐使用 | 高波特率、长时间传输 | 临时调试、低波特率 |
所以记住一个核心原则:能用 PL011 就绝不用 mini UART。后面所有配置动作,基本都是为了把这个原则落实到位。
1.2 设备节点映射:ttyAMA0、ttyS0到底谁是谁
Linux 下每个串口控制器都会暴露成一个字符设备,树莓派上最常见的就是ttyAMA0和ttyS0。但这两个名字和物理引脚之间不是固定对应关系,它俩的映射会受蓝牙、设备树配置、内核cmdline参数影响。
以树莓派3B/3B+/4B为例,最常见的情况是这样的:
- 板载蓝牙开启时:蓝牙固件占用 PL011,
ttyAMA0被分配给蓝牙使用;GPIO14/15上的串口变成 mini UART,设备节点是ttyS0。 - 板载蓝牙关闭时:
ttyAMA0(PL011)回到 GPIO14/15,成为真正的用户串口。
Linux为了不让应用层直接面对这种混乱,又提供了两个软链接:/dev/serial0和/dev/serial1。它们由udev根据设备树别名自动创建,其中serial0通常指向40pin排针上的主串口,serial1通常指向蓝牙对应的串口。所以我更推荐你在代码和工具里一律使用/dev/serial0,而不是写死ttyAMA0或ttyS0。这样即使你换一台机器、改了一种配置,应用层代码都不用动。
有经验的开发者还会留意/proc/device-tree/aliases/目录,里面直接存着 serial0 和 serial1 的指向。这个目录里的内容比/dev下的软链接更底层,排查问题时价值很大。
1.3 40pin排针上真正能用的串口引脚
40pin排针上默认的串口引脚非常固定:GPIO14 对应 TXD,GPIO15 对应 RXD。物理引脚编号分别是8号和10号。GND 随便取一个即可,常用6号或9号引脚。
这里必须强调一个新手极其容易踩的坑:树莓派的串口是3.3V TTL 电平,不是 RS232 电平,也不是5V电平。你用USB转串口模块连接时,必须把模块跳到3.3V档位;用STM32、ESP32这类3.3V单板连接时,直接TX-RX、RX-TX、GND-GND交叉相接即可。如果对方是5V逻辑的Arduino老款板子,强烈建议加电平转换模块,或者使用3.3V版本的开发板,否则轻则通信异常,重则直接烧掉树莓派GPIO。
另外,GPIO14/15在树莓派上还有其他复用功能,比如I2S、PCM等,使用时需要确认没有其他外设抢占。不过绝大多数情况下,系统默认就会把它们作为串口功能,我们真正要处理的其实是“系统自身占用”的问题,这一点在第三章详细展开。
2. 实用第一课:确认 GPIO14/15 上到底是哪个串口
2.1 通过设备树别名快速定位
拿到一台树莓派,第一步不是急着写代码,而是确认当前系统到底把哪个设备节点映射到了 GPIO14/15 上。最简单的方法就是看serial0指向哪里:
ls -l /dev/serial*正常情况下你会看到类似这样的输出:
lrwxrwxrwx 1 root root 5 xxx /dev/serial0 -> ttyS0 lrwxrwxrwx 1 root root 5 xxx /dev/serial1 -> ttyAMA0这表示 GPIO14/15 当前走的是ttyS0,也就是 mini UART;而ttyAMA0被蓝牙占了。如果你已经关了蓝牙并清掉了控制台参数,就可能看到相反的结果:/dev/serial0 -> ttyAMA0。
再深入一点,可以查看/proc/device-tree/aliases/uart*:
cat /proc/device-tree/aliases/uart*以及内核日志里对每个tty设备的初始化信息:
dmesg | grep tty这些命令组合起来,能在半分钟内把一台陌生树莓派的串口拓扑摸清。我自己拿到新板子或者刷了新镜像后,一定会先跑一遍这几个命令,再决定后续配置方案。
2.2 检查串口是否被控制台占用
很多人在串口上收发数据时发现“写入成功但没有任何输出”,或者更迷惑的是——树莓派重启时串口里冒出一堆内核日志,然后就安静了。这通常意味着你的串口被当作Linux 内核控制台或登录终端占用了。
占用串口的主要有两类进程:一是内核 cmdline 里的console=serial0,115200参数,它会把内核日志输出重定向到串口;二是 systemd 的serial-getty@ttyAMA0.service或serial-getty@ttyS0.service,它会在这个串口上跑一个登录终端。两者只要有一个在工作,你的用户程序就无法独占串口。
检查方法:
sudo systemctl status "serial-getty*" cat /boot/firmware/cmdline.txt # 旧版本镜像路径是 /boot/cmdline.txt如果服务是 running,或者 cmdline 里出现了console=serial0/console=ttyAMA0/console=ttyS0,那就说明串口被系统占用了。解决方案在第三章,这里只需要先养成“写串口前先查占用”的习惯。
2.3 回环测试验证通道
在你修改任何配置之前,先做一次回环测试,确认硬件物理链路是通的。把树莓派 GPIO14(物理8号)和 GPIO15(物理10号)用一个杜邦线直接短接,然后用串口工具往serial0发一条数据。因为 TX 和 RX 短接,自己发的内容会原样传回自己。
在命令行里可以用minicom或picocom,也能用一段很短的 Python 把收发一次测完:
import serial ser = serial.Serial('/dev/serial0', 115200, timeout=1) ser.write(b'hello rpi\r\n') data = ser.read(64) print('received:', data) ser.close()如果能正常打印出received: b'hello rpi\r\n',说明从系统到引脚的整条链路通畅。如果这里就不通,别急着改系统配置,先去检查引脚短接是否牢固、杜邦线是否损坏、设备路径是否选对。回环测试能帮你把问题范围快速缩小到“硬件链路”还是“软件配置”。
3. 串口能用之前的三个配置动作
3.1 给当前用户加 dialout 权限
树莓派系统里的串口设备默认属于root:dialout,普通用户直接访问会出现Permission denied。解决办法不是用sudo chmod 666,而是把当前用户加入 dialout 组:
sudo usermod -aG dialout $USER执行完这条命令后,必须重新登录或者重启会话,用户组权限才会生效。如果你是在终端里操作,直接重启树莓派是最省心的。
我见过不少人在/dev/ttyS0上遇到Permission denied后,习惯性加个 sudo 去跑程序,这样虽然能用,但在 ROS2、Docker 这类环境里权限管理会非常混乱。正确姿势是把自己加入 dialout 组,让普通用户也能直接访问串口设备,后续调试轻松得多。
另外提醒一句,Ubuntu 22.04 等系统上,用户可能叫ubuntu,命令一样:
sudo usermod -aG dialout ubuntu改完记得验证:
id看输出里有没有dialout。
3.2 关掉内核控制台和登录 shell,把主串口让出来
这是整个配置里最关键的一步。推荐用树莓派官方的raspi-config来做,因为它会同步修改 cmdline、systemd 服务等一堆关联配置,不容易出错:
sudo raspi-config进入Interface Options -> Serial Port,它会连续问两个问题:
Would you like a login shell to be accessible over serial?(要不要把串口作为登录终端?)——选No。Would you like the serial port hardware to be enabled?(要不要启用串口硬件?)——选Yes。
选完重启,GPIO14/15 上就没有 console 和 getty 抢占了。如果你更喜欢手动改,步骤也直观,以新版 Raspberry Pi OS / Ubuntu 22.04 为例:
先编辑/boot/firmware/cmdline.txt,把里面console=serial0,115200或console=ttyAMA0,115200删除,保留其他内核参数。比如原来是:
console=serial0,115200 console=tty1 root=PARTUUID=xxx rootfstype=ext4 fsck.repair=yes rootwait改成:
console=tty1 root=PARTUUID=xxx rootfstype=ext4 fsck.repair=yes rootwait然后再编辑/boot/firmware/config.txt,确认加入:
enable_uart=1旧版系统路径是/boot/config.txt和/boot/cmdline.txt,操作逻辑一样。
手动改配置时特别提醒:cmdline.txt 必须是单行文本,千万别手滑按了换行,否则内核启动会直接失败。改完先用cat检查,再重启。
3.3 enable_uart=1 什么时候必须写
enable_uart=1这个参数在不同时代的树莓派系统里作用不太一样。早期固件默认会把 GPIO14/15 当作内核串口控制台,且 UART 功能可能是关闭状态,需要显式加上enable_uart=1才能把硬件串口释放给用户。到了较新的 Raspberry Pi OS 里,很多镜像已经默认开启了串口, 但仍建议保留这一行,尤其是在 Ubuntu 这类非官方系统上,缺少它可能导致 GPIO14/15 完全没有信号。
判断是否生效很简单:重启后执行:
ls -l /dev/serial0如果软链接存在且指向一个真实设备,说明硬件串口已被注册。如果/dev/serial0都找不到,大概率是enable_uart=1没写或者被其他 overlay 覆盖了。
4. 蓝牙与PL011的历史纠葛:树莓派3/4B的串口名为什么总变
4.1 蓝牙到底占用了哪个串口
从树莓派3开始,板载蓝牙与处理器的通信就通过 UART 连接。为了获得稳定的蓝牙吞吐,博通在硬件层面把 PL011(也就是ttyAMA0)分配给了蓝牙控制器,40pin排针上的串口则被迫使用 mini UART(ttyS0)。
这就解释了为什么很多老玩家会说“树莓派3以后的串口变垃圾了”:不是串口本身消失,而是你拿到手的就是那个没独立时钟、波特率随CPU负载飘的 mini UART。尤其是跑桌面系统时,CPU频率上下跳动,115200下丢包和乱码是家常便饭。
在树莓派4B上,这个结构依然没有本质变化。所以如果你在4B上做项目,同时还想用 GPIO14/15 的串口,基本只有两条路:关掉蓝牙抢回 PL011,或者接受 mini UART 的性能损失。
4.2 关闭蓝牙抢回 PL011
如果你的项目不需要板载蓝牙,最推荐的做法是直接禁用蓝牙,把 PL011 请回 GPIO14/15。在/boot/firmware/config.txt中加入:
dtoverlay=disable-bt同时按3.2节的方法删掉 cmdline 里的console=serial0,115200,重启后执行:
ls -l /dev/serial*你会看到serial0 -> ttyAMA0,GPIO14/15 终于回归 PL011。这才是做机器人、传感器采集、高速串口桥接时该有的串口状态。旧的 overlay 名字也叫pi3-disable-bt,在新内核里统一成了disable-bt,如果你查老资料看到前者,不要惊讶。
但要注意,这个操作会直接屏蔽板载蓝牙控制器,你的无线键盘、蓝牙音箱、蓝牙手柄都会断联。如果只是偶尔用蓝牙,不建议走这条方案。
4.3 mini UART 的波特率漂移与锁频
如果你确实要保留蓝牙,又不得不暂时用 mini UART,那就要正视它的波特率漂移问题。mini UART 的时钟来自GPU核心频率,默认情况下核心频率会随CPU负载动态调整。负载一高,波特率就不再是标称值,接收端自然解码失败。
老办法是在 config.txt 里锁定核心频率:
core_freq=250早期内核里这个参数有效,但到树莓派4B之后,核心频率管理的策略变了,锁频效果很有限,甚至可能影响其他外设性能。所以我的建议很直接:不要和 mini UART 纠缠,项目里买一个USB转串口模块都比死磕它划算。这也是很多树莓派爱好者到了最后殊途同归的选择。
5. 树莓派5的串口扩展:RP1带来更多可能
5.1 树莓派5的串口体系变化
树莓派5 在IO架构上做了大调整,核心是启用了自研的 RP1 芯片作为IO控制器,串口资源也随之丰富起来。它不像树莓派4B那样只有一个 PL011 加一个 mini UART 的简陋局面,而是提供了多路UART,可以更灵活地映射到40pin排针的不同引脚上。同时,树莓派5 的蓝牙资源不再直接抢占主串口,默认情况下 GPIO14/15 就能拿到品质良好的 UART 通道,这让很多在4B上被蓝牙折磨过的开发者长舒一口气。
需要注意的是,树莓派5 的串口设备名也变多了。除了经典的ttyAMA0,启用额外串口后还会出现ttyS0、ttyS1、ttyS2等一堆节点。具体哪个节点对应哪个引脚,最好用dmesg | grep tty确认,或者直接查/proc/device-tree/aliases/,不要靠猜。
5.2 通过设备树 overlay 启用额外UART
树莓派5 上如果想引出第二路、第三路串口,不需要外接USB转串口,直接在 config.txt 里启用对应的设备树 overlay 即可。以典型的uart2-pinout为例:
dtoverlay=uart2-pinout重启后执行:
ls -l /dev/tty*大概率会看到新增了一个 tty 节点,同时可以在 dmesg 里确认它绑定到了哪个引脚组。这里的“pinout”后缀决定了引脚位置,不同版本固件支持的引脚组合略有差异,务必以官方手册为准。这类overlay 的好处是,你可以把多路传感器分别挂在不同串口上互不干扰,非常适合搞机器人或者多设备通信的场景。
不过也要提醒一句:树莓派5 的额外UART虽然多,但部分引脚可能需要和其他功能复用,启用前最好先看一眼当前项目的GPIO分配表,避免两个外设打架。
5.3 树莓派Pico的UART别搞混
经常有人把树莓派Pico和树莓派Linux系统放在一起聊,然后被串口命名弄晕。Pico是单片机,运行的是MicroPython或C固件,没有/dev/ttyAMA0这套东西。它的 RP2040 芯片内部有两路硬件UART,分别叫uart0和uart1,需要在自己代码里指定TX/RX引脚和波特率:
from machine import UART, Pin uart = UART(0, baudrate=115200, tx=Pin(0), rx=Pin(1)) uart.write(b'ping') print(uart.read())如果你同时玩树莓派SBC和Pico,会自动发现两者的串口完全是两套体系。Pico这边由你自己全权控制,没有蓝牙抢占、没有console占用,反而省心得多。团队里有人做Pico控制舵机、有人做树莓派上层逻辑,最关键的就是把两边的串口参数统一好,然后通过TX、RX、GND三根线对接。
6. USB转串口:把树莓派的串口数量翻倍
6.1 CH340、CP2102、FTDI怎么选
树莓派本身的串口引脚有限,尤其4B时代更是捉襟见肘。这时候最通用的扩展方案就是 USB 转串口,一根线插上,系统就会多出一个/dev/ttyUSB0(或ttyACM0)。市面上最常见的三种芯片是 CH340、CP2102 和 FTDI,价格和稳定性差异明显:
| 芯片 | 常见品牌/模块 | 驱动 | 稳定性 | 适用场景 |
|---|---|---|---|---|
| CH340 | 蓝色/绿色小板 | Linux内核ch341驱动 | 尚可 | 刷机、低波特率调试 |
| CP2102 | 黑壳小棒、紫板 | cp210x驱动 | 较稳定 | 常规串口调试 |
| FTDI | FT232 | ftdi_sio驱动 | 高 | 高波特率、工业级项目 |
在树莓派上,这三种芯片通常都是免驱的,插上就会自动识别。如果插上后没出设备,先dmesg | tail看内核日志,多数情况是线材问题或接触不良。CH340 从价格角度适合随便用用,但如果项目里要做高速、长时限的串口通信,建议直接买 FTDI 或 CP2102,避免后期因为驱动稳定性问题浪费几天时间。
还有些USB转串口模块默认输出5V电平,插到树莓派前一定要确认模块的跳线帽是不是3.3V档。这个细节一疏忽,轻则串口乱码,重则烧引脚。
6.2 电平、共地和接线禁忌
连接USB转串口模块和树莓派时,接线必须遵循交叉原则:树莓派 TX 接模块 RX,树莓派 RX 接模块 TX,GND 接 GND。串口通信的收发节点天然是反的,如果你把它俩的TX接TX、RX接RX,两个发送端互怼,互相驱动,不仅收不到数据,还可能造成损坏。
共地也是一定要强调的点。两个设备之间只有把GND连起来,参考电平才能一致,否则信号电压完全没法判定高低电平。很多“串口发不出数据”的诡异问题,最后查出来就是GND没接。
另外,前文提到的3.3V TTL电平问题,在连接STM32、ESP32、Arduino等设备时同样适用。如果你有一个1.8V的串口传感器,还需要用三极管或专用电平转换芯片把电平抬到3.3V,千万不要尝试直接把1.8V信号接在树莓派3.3V引脚上。
7. 常见的串口调试工具与最小收发示例
7.1 minicom、picocom 的基本用法
命令行下最常用的串口工具是minicom和picocom,安装都很简单:
sudo apt install minicom picocomminicom 功能全,但交互方式比较老派,进入串口后按Ctrl+A再按Z可以打开帮助菜单,退出是Ctrl+A再按X。连接命令:
minicom -D /dev/serial0 -b 115200picocom 就轻量得多,适合快速看一眼收发是否正常:
picocom -b 115200 /dev/serial0退出序列是Ctrl+A Ctrl+X。它启动时默认是原始模式,不会像 minicom 那样自行翻译控制字符,观察十六进制数据时更准确。
我用得最多的其实是 picocom,因为不折腾、开箱即用,适合在调试现场快速确认串口状态。minicom 则适合需要保存配置、定期连接同一个设备的场景。
7.2 Python pyserial 快速收发
做项目时,用 Python 直接读写串口往往比命令行更顺手。安装依赖:
pip install pyserial然后一个最简收发程序:
import serial ser = serial.Serial( port='/dev/serial0', baudrate=115200, bytesize=8, parity='N', stopbits=1, timeout=0.1 ) ser.write(b'AT\r\n') resp = ser.read(128) print(resp) ser.close()这里bytesize=8, parity='N', stopbits=1就是常说的“8N1”格式。绝大多数串口外设的默认参数都是 8N1,如果你的设备手册写着其他格式,比如“7E1”或“8N2”,对应修改这几个参数即可。
timeout 参数也非常关键。它告诉串口在无数据时最多等待多少秒,避免read()无限阻塞。实际开发里,我会根据设备的响应速度自由调整,比如GPS模块通常 100ms 内就会有数据返回,而某些老式传感器可能要等 500ms 以上。
7.3 调参要点:8N1、波特率与超时
串口通信的参数并不复杂,但必须和另一端设备完全对齐。首先确认波特率,两端不一致时你会看到满屏乱码或者偶尔几个字节正确。其次是数据位、停止位和校验位,一般设备手册都会明确写“115200, 8, N, 1”这样的格式,照抄即可。第三是流控,如果你的外设没有 RTS/CTS 硬件流控,串口的rtscts参数一定不要开,否则双方都无法正常收发。
在树莓派上还有一类特殊问题:当设备是 mini UART 时,CPU 负载会影响实际波特率,即使用 115200 配置也可能收到错码。处理方案我们不重复了,唯一要记住的判断思路是:如果回环测试正常,但接了对方设备就乱码,优先怀疑波特率漂移或电平不匹配。
8. 常见问题与排查技巧实录
8.1 串口故障速查表
结合这些年的实际经验,我把树莓派串口场景里最高频的问题整理成一个速查表,按“现象 -> 原因 -> 处理”的顺序来:
| 故障现象 | 大概率原因 | 处理办法 |
|---|---|---|
| 访问报 Permission denied | 用户不在 dialout 组 | sudo usermod -aG dialout $USER后重新登录 |
| 串口写入成功但无输出 | 串口被 console/getty 占用 | 清除 cmdline 串口参数,关闭 serial-getty |
| 接外设全乱码,回环正常 | 波特率不匹配、电平不匹配、mini UART漂移 | 核对参数,优先用 PL011 |
| 重启后串口没设备节点 | enable_uart=1缺失 | config.txt 加enable_uart=1 |
| 蓝牙设备突然消失 | 启用了disable-bt | 删除对应 overlay |
| USB转串口插上无 ttyUSB0 | 驱动没加载、线材问题、供电不足 | dmesg查日志,换线测试 |
| 接STM32/ESP32时偶尔丢包 | 线太长、供电不稳、波特率过高 | 缩短杜邦线、降波特率、共地 |
| GPIO14/15接5V模块后无信号 | 电平不匹配或引脚受损 | 用3.3V模块或电平转换板 |
这张表基本覆盖了从硬件到软件的所有坑。真到排查现场,按表格顺序逐项排除,比瞎猜高效得多。
8.2 三个现场排查案例
第一个案例是典型的“新系统串口默认关闭”问题。用户拿树莓派4B刷了 Ubuntu 22.04,GPIO14/15 上始终没有任何信号输出,ls /dev/serial*直接没有软链接。查了一圈发现/boot/firmware/config.txt里根本没写enable_uart=1。加上这一行重启后,/dev/serial0立刻出现,串口恢复正常。很多人以为官方树莓派OS能用,Ubuntu也能用,其实这类系统默认裁剪比较狠,必须自己补配置。
第二个案例来自一个ROS2小车项目。树莓派4B上跑 ROS2 humble,需要通过 GPIO 串口桥接 ESP32 底盘控制器,同时还有一个USB转串口接了雷达模块。最初系统里 GPIO 串口被蓝牙占成了ttyS0,控制指令总丢,小车一抖一抖。最后就是加了dtoverlay=disable-bt,清掉 cmdline 里的串口 console,GPIO 串口变成ttyAMA0,波特率一下子就稳了,底盘控制延迟明显下降。这个案例很典型:机器人场景里,PL011 是底线,mini UART 根本不够看。
第三个案例是USB转串口模块驱动问题。插上 CP2102 模块后树莓派完全没有反应,ls /dev/ttyUSB0报不存在。执行dmesg | tail发现内核输出提示usb设备断开,把模块插到另一个USB口,问题立刻消失——原来是树莓派USB口供电不稳,带不动部分模块。后来换了一根供电粗一点的短线才彻底解决。USB转串口看似小事,供电和线材质量直接决定稳定性。
这三个案例覆盖了配置缺失、硬件资源抢占、供电不稳定三类树莓派串口最常见事故。如果你按前面的步骤把地基打牢,再遇到问题基本都能从这张速查表里找到答案。
最后分享一点个人习惯。我拿到任何一台树莓派,第一步从来不是急着装软件,而是先跑一遍dmesg | grep tty和ls -l /dev/serial*,把当前串口映射记在纸上。做项目的原则也很简单:能用 PL011 就不要碰 mini UART,能用/dev/serial0就不要硬记ttyAMA0和ttyS0,需要蓝牙又需要串口的时候,优先考虑USB转串口而不是跟设备树死磕。这套原则帮我从树莓派3一路用到了树莓派5,踩过的坑基本都写在前面了。如果你也遇到过串口名总是“漂移”的问题,不妨先从关闭蓝牙、清空串口控制台这两步开始排查,多半能省下好几个晚上。