树莓派串口通信实战:从配置到稳定收发的完整指南
你有没有遇到过这种情况——硬件接好了,代码写完了,可树莓派就是收不到传感器的数据?或者好不容易收到几个字节,结果乱码频出、断断续续?
别急,这大概率不是你的程序有问题,而是串口没配对。
在物联网项目中,树莓派通过 UART 与 STM32、Arduino 或 GPS 模块通信再常见不过。但很多开发者卡在第一步:明明线都接对了,为什么就是“通不了”?根源往往藏在系统级配置里——尤其是那个看似简单的raspi-config工具。
今天我们就来彻底讲清楚:如何用官方推荐的方式,把树莓派的串口真正“打开”,并实现稳定可靠的双向通信。
一、先搞明白:树莓派的串口到底有几个?
很多人以为树莓派只有一个串口,其实不然。它的 SoC(比如 BCM2837)内置了多个 UART 控制器,但对外只引出了两个主要的:
PL011 UART(通常映射为
/dev/ttyAMA0)
功能完整,波特率精准,不受 CPU 频率变化影响,适合高可靠性通信。mini UART(通常映射为
/dev/ttyS0)
简化版,依赖系统主频。一旦 CPU 进入节能模式降频,波特率就会漂移,导致通信失败。
更麻烦的是,默认情况下:
✅ 在树莓派 3B+ 及以后型号上,蓝牙占用了 PL011 UART,而普通用户能用的只剩不稳定的 mini UART。
所以如果你直接连上 GPIO14/15 去通信,哪怕波特率设成 115200,也可能因为频率波动而出错。
那怎么办?答案是:把蓝牙关掉,把高性能串口还给用户。
二、正确姿势:用raspi-config解锁主串口
最安全、最推荐的方法,就是使用树莓派官方工具raspi-config来完成配置。它不仅能帮你修改底层文件,还会自动处理依赖关系,比如禁用蓝牙服务。
第一步:启动配置工具
sudo raspi-config进入图形化菜单后,选择:
👉Interfacing Options → Serial Port
接下来会问你两个关键问题:
❓ “Would you like a login shell to be accessible over serial?”
→ 选No
这是重点!如果选 Yes,系统会在启动时通过串口输出日志(即“串口控制台”),相当于一直有数据往外刷,严重干扰你的应用通信。
❓ “Would you like the serial port hardware to be enabled?”
→ 选Yes
这一步才是真正启用 UART 硬件接口,允许用户程序访问。
完成后保存退出,并重启:
sudo reboot三、背后发生了什么?配置生效的原理
你以为点几下鼠标就完事了?其实raspi-config在后台默默做了不少事:
移除串口控制台参数
它会从/boot/cmdline.txt中删掉类似console=serial0,115200的字段,防止内核打印占用串口。停止 getty 服务
禁用getty@ttyS0.service,避免系统试图在串口上启动登录终端。释放 PL011 UART 资源
如果检测到板载蓝牙(如 Pi 3B+/4B),会自动向/boot/config.txt添加:ini dtoverlay=disable-bt
这句话的意思是:“别让蓝牙用我的好串口了”。强制启用 UART 硬件
同时建议添加:ini enable_uart=1
因为树莓派默认可能会为了省电动态关闭 UART,加这一行才能确保它始终在线。
🔍 小贴士:你可以手动检查
/boot/config.txt是否包含这两行,没有就补上。
四、验证是否成功:看看串口归谁管了
重启之后,先别急着跑代码,先确认系统已经把正确的串口暴露给你。
执行命令:
ls -l /dev/serial*正常情况下你应该看到:
lrwxrwxrwx 1 root root 7 Apr 5 10:00 /dev/serial0 -> ttyAMA0注意看——/dev/serial0指向的是ttyAMA0!
这意味着:
✅ 高性能的 PL011 UART 已被启用
✅ 蓝牙已被禁用或重定向
✅ 你现在使用的不再是那个容易漂移的 mini UART
如果是-> ttyS0,那就说明还在用 mini UART,通信质量无法保证。
五、权限问题:别让“Permission denied”拦住你
即使设备节点出来了,运行 Python 脚本时仍可能报错:
OSError: [Errno 13] Permission denied: '/dev/serial0'原因很简单:当前用户没有访问串口的权限。
Linux 把串口设备归类为dialout用户组管理。解决方法是一行命令:
sudo usermod -aG dialout $USER然后重新登录或重启,让组权限生效。
💡 提示:
$USER会自动替换成当前用户名,比如 pi 或 ubuntu。
六、动手实操:Python 接收 STM32 发来的数据
现在万事俱备,来个真实场景演示。
假设你有一块 STM32 开发板,每隔 1 秒通过串口发送一行 JSON 数据:
{"temp":25.3,"humid":60}树莓派这边只需一个简单的接收脚本即可捕获。
安装 PySerial
pip install pyserial编写通信脚本
import serial import time # 打开串口 —— 记住,永远优先用 /dev/serial0 ser = serial.Serial( port='/dev/serial0', # 不要硬编码 ttyS0/ttyAMA0 baudrate=115200, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=1 # read() 最多等 1 秒 ) print("Waiting for data...") try: while True: if ser.in_waiting > 0: # 有数据到达 line = ser.readline().decode('utf-8').strip() print(f"Received: {line}") except KeyboardInterrupt: print("\nExiting...") finally: ser.close()运行这个脚本,你会看到实时打印出传感器数据。
✅ 成功标志:数据连续、无乱码、无丢包。
七、避坑指南:这些错误90%的人都踩过
| 问题现象 | 根本原因 | 解决方案 |
|---|---|---|
| 收不到任何数据 | 串口控制台仍在运行 | 用raspi-config关闭 shell over serial |
| 数据偶尔错乱 | 使用了 mini UART(ttyS0) | 添加enable_uart=1+dtoverlay=disable-bt |
/dev/serial0不存在 | UART 被完全禁用 | 检查config.txt是否启用了 UART |
| 蓝牙不能用了 | disable-bt关掉了蓝牙 | 如需蓝牙共存,改用 USB 转串口模块 |
| Permission denied | 用户不在dialout组 | 执行sudo usermod -aG dialout pi |
特别提醒:有些教程教你改cmdline.txt却忘了停getty服务,结果还是收不到数据——一定要两者都做。
八、进阶建议:什么时候该换 USB 转串口?
虽然我们可以通过禁用蓝牙来获得高性能串口,但这意味着牺牲了蓝牙功能。
如果你的项目同时需要:
- 使用蓝牙(例如连接 BLE 传感器)
- 高速稳定的串口通信(如 921600 bps)
那么更好的方案是:
🔌外接 USB-to-UART 模块(如 CP2102、FT232RL、CH340)
优势非常明显:
- 不占用树莓派有限的 GPIO 资源
- 即插即用,无需改动系统配置
- 支持更高波特率和更稳定的传输
- 可同时保留蓝牙、Wi-Fi 和串口功能
这类模块十几块钱一个,性价比极高,强烈推荐用于复杂项目或多设备调试。
九、最佳实践总结:老手是怎么做的?
永远使用
/dev/serial0
而不是/dev/ttyS0或/dev/ttyAMA0,这样写的程序能在不同代际的树莓派上无缝运行。首次配置必走
raspi-config流程
安全、完整、自动化,避免遗漏关键步骤。手动补上
enable_uart=1
别指望raspi-config万能,自己打开/boot/config.txt确认更安心。开发阶段可用 systemctl 临时调试
想快速测试又不想重启?可以临时停服务:bash sudo systemctl stop getty@ttyS0.service生产环境优先考虑 USB 串口适配器
特别是在需要保留蓝牙或双串口通信的场景下。
写在最后
树莓派串口通信看似简单,实则暗藏玄机。真正的难点不在代码,而在理解系统的资源分配逻辑。
当你学会用raspi-config正确释放 PL011 UART,当你看到/dev/serial0 -> ttyAMA0的那一刻,你就已经跨过了大多数初学者止步的门槛。
记住一句话:
🌟好的嵌入式工程师,不是会写代码的人,而是知道系统为什么会不工作的人。
下次再遇到“串口不通”,别急着换线、换模块、重装系统。静下心来看看配置,也许答案就在/boot/config.txt里。
如果你正在做一个基于串口的物联网项目,欢迎在评论区分享你的架构设计,我们一起讨论优化方案。