树莓派5串口通信实战指南:从引脚定义到稳定通信的完整路径
你有没有遇到过这样的情况——接好了线,写好了代码,树莓派却收不到GPS模块的数据?或者串口输出全是乱码,调试信息像天书一样?
别急,这多半不是你的程序出了问题,而是UART引脚配置没搞明白。尤其是刚从树莓派3/4迁移过来的朋友,面对树莓派5的新电源架构和设备树机制,很容易在“看似简单”的串口通信上栽跟头。
今天我们就来彻底讲清楚:树莓派5到底哪些引脚能用来做串口?怎么用才不会出错?主串口和迷你串口有什么区别?为什么有时候明明连对了就是不通?
我们不堆术语,不抄手册,只讲你在开发板前真正需要知道的东西。
为什么UART仍是嵌入式开发的“基本功”?
尽管I²C、SPI甚至以太网都越来越普及,但UART依然是最实用、最可靠的调试与通信手段之一。原因很简单:
- 只需两根信号线(TX/RX)+ 地线就能双向通信
- 几乎所有微控制器、传感器、模组都支持
- Linux系统默认通过串口输出启动日志(console)
- 不依赖时钟线,布线灵活,适合长距离传输(配合电平转换)
更重要的是,当你SSH连不上、网络不通的时候,只有串口还能救你一命。
而要让这一切正常工作,第一步就是搞清物理引脚和功能映射之间的关系。
树莓派5的40针GPIO里,哪几个是用来跑UART的?
树莓派5延续了经典的40针排布,但内部SoC(BCM2712)的功能复用逻辑更复杂了。我们先看最关键的两个引脚:
| 物理引脚 | BCM编号 | 默认功能 | 实际用途 |
|---|---|---|---|
| Pin 8 | GPIO14 | UART0_TXD | 主串口发送端 → 接外部设备RX |
| Pin 10 | GPIO15 | UART0_RXD | 主串口接收端 ← 接外部设备TX |
| Pin 6 | —— | GND | 共地!必须连接 |
✅结论先行:
如果你要接 GPS、蓝牙、Wi-Fi 模组或任何串口设备,优先使用 Pin 8 和 Pin 10,也就是 GPIO14 和 GPIO15。
这两个引脚对应的是Primary UART(PL011 UART0),性能强、稳定性高,是官方推荐用于关键通信的通道。
那其他GPIO也能当串口用吗?
可以,但有条件。
比如:
- GPIO16 / GPIO17(Pin 28 / Pin 27)可配置为 Mini UART 的 TX/RX
- 其他GPIO可通过软件模拟(bit-banging),但仅限低速场景
不过我们要重点提醒一句:Mini UART 是个“坑点密集区”,稍后细说。
Primary UART vs Mini UART:别再傻傻分不清
很多人踩坑,就是因为不知道树莓派有两个串口控制器。它们的区别,直接决定了你项目的成败。
| 对比项 | Primary UART (UART0) | Mini UART (SBI UART) |
|---|---|---|
| 设备节点 | /dev/ttyAMA0 | /dev/ttyS0 |
| 控制器类型 | PL011(工业级IP核) | 简化版 SBI |
| 波特率稳定性 | 高(独立时钟源) | 低(依赖 core_freq 动态变化) |
| FIFO 缓冲区 | 16字节,有效防丢包 | 极小,易溢出 |
| 是否受CPU频率影响 | 否 | 是! |
| 默认是否启用 | 是(常作控制台) | 否 |
| 适用场景 | 关键通信、高速传输、工业应用 | 调试烧录、低速传感等非核心任务 |
举个真实案例:
一位开发者用 Mini UART 连接一个波特率为 115200 的温湿度传感器,白天运行正常,晚上偶尔断联。查了一周才发现:系统节能模式下调低了 core_freq,导致实际波特率偏差超过容限!
解决方法?换成/dev/ttyAMA0,问题消失。
所以记住一句话:
要做可靠通信,就用 Primary UART;Mini UART 只适合临时用途。
如何正确启用串口?三步走,一步都不能少
很多初学者以为“插上线就能通”,结果发现根本读不到数据。其实背后有三个关键步骤必须完成:
第一步:关闭串口登录 shell(禁用控制台)
这是最常见的冲突来源!
树莓派出厂默认把串口当作系统控制台使用,意味着:
- 内核启动信息会从串口输出
- 系统还会监听串口等待用户登录
这就占用了/dev/ttyAMA0,你的程序自然打不开它。
✅ 解决方案:
运行:
sudo raspi-config进入Interfacing Options → Serial Port:
- 是否启用登录 shell? →No
- 是否启用硬件串口? →Yes
保存退出并重启。
或者手动编辑/boot/firmware/cmdline.txt,删除其中的:
console=serial0,115200⚠️ 注意:树莓派5的配置文件路径是
/boot/firmware/,不再是旧版的/boot/!
第二步:确保用户有权访问串口设备
Linux下串口设备属于dialout组,默认普通用户无权操作。
运行这条命令把你当前用户加进去:
sudo usermod -aG dialout $USER然后注销重新登录,权限才会生效。
验证是否成功:
ls -l /dev/ttyAMA0应看到类似:
crw-rw---- 1 root dialout 204, 64 Apr 5 10:00 /dev/ttyAMA0如果你的用户名在dialout组里,就可以读写了。
第三步:正确选择设备节点
记住这个对应关系:
| UART 类型 | Linux设备节点 | 推荐用途 |
|---|---|---|
| Primary UART | /dev/ttyAMA0 | 外设通信、调试输出 |
| Mini UART | /dev/ttyS0 | 辅助通道(需手动启用) |
如果要用 Mini UART(比如主串口已被占用),还需要在/boot/firmware/config.txt中添加:
dtoverlay=uart1然后重启生效。
实战代码示例:C语言 & Python 怎么写?
C语言:直接操作 ttyAMA0 发送数据
#include <stdio.h> #include <fcntl.h> #include <termios.h> #include <unistd.h> int main() { int fd = open("/dev/ttyAMA0", O_RDWR); struct termios options; if (fd == -1) { perror("无法打开串口"); return -1; } tcgetattr(fd, &options); cfsetispeed(&options, B115200); cfsetospeed(&options, B115200); options.c_cflag = (options.c_cflag & ~CSIZE) | CS8; // 8位数据 options.c_cflag &= ~(PARENB | CSTOPB); // 无校验,1停止位 options.c_cflag |= CLOCAL | CREAD; // 启用接收 tcsetattr(fd, TCSANOW, &options); write(fd, "Hello Pi5!\n", 11); close(fd); return 0; }编译运行:
gcc uart_send.c -o uart_send ./uart_send💡 提示:若提示权限错误,请确认已加入
dialout组。
Python:用 pyserial 快速实现收发循环
安装依赖:
pip install pyserial代码如下:
import serial import time # 打开主串口,波特率115200 ser = serial.Serial('/dev/ttyAMA0', 115200, timeout=1) try: while True: ser.write(b'Ping\n') response = ser.readline() if response: print(f"收到: {response.decode().strip()}") time.sleep(1) except KeyboardInterrupt: print("\n退出") finally: ser.close()这段代码每秒发一次“Ping”,并监听回应,非常适合测试传感器回传。
常见问题排查清单(附解决方案)
| 问题现象 | 可能原因 | 解决办法 |
|---|---|---|
Permission denied | 用户未加入dialout组 | sudo usermod -aG dialout $USER |
| 收到乱码或数据错乱 | 波特率不匹配 / Mini UART频率漂移 | 检查双方设置;改用/dev/ttyAMA0;锁定core_freq=250 |
| 串口完全打不开 | 被系统控制台占用 | 用raspi-config关闭串口登录 |
| 数据丢失频繁 | 使用了 Mini UART 且无流控 | 改用 Primary UART 或降低波特率 |
| 连接 Arduino 时损坏树莓派 | 5V电平直接接入 GPIO(致命错误!) | 必须使用双向电平转换器(如 TXS0108E) |
🔥血泪教训提醒:
树莓派所有GPIO都是3.3V TTL电平,绝对不能直接接5V设备!
即使只是短暂通电,也可能永久损坏SoC。
对接 Arduino Uno、STM32F103 等5V系统时,请务必使用电平转换模块。
最佳实践建议:老手是怎么做的?
始终优先使用 GPIO14/GPIO15(Pin 8/10)作为主通信通道
- 性能稳、兼容好、不易出问题调试阶段开启串口日志记录
bash screen /dev/ttyAMA0 115200 > log.txt
把原始数据存下来,方便事后分析协议格式或异常行为。避免热插拔
- 插拔瞬间可能产生电压尖峰
- 建议断电接线,或使用光耦/磁耦隔离模块多串口需求怎么办?
- 方案一:USB转TTL适配器(CP2102、CH340)——即插即用
- 方案二:I²C/SPI转UART桥芯片(如 MCP2200)——节省USB口
- 方案三:软件模拟UART(仅限<9600bps)生产环境建议固定核心频率
若不得不使用 Mini UART,可在config.txt添加:ini core_freq=250
防止动态调频导致波特率失准。
写在最后:掌握串口,才算真正入门嵌入式
你看,UART看起来只是“发几个字节”的小事,但它背后涉及:
- 引脚复用机制
- 设备树配置
- 权限管理
- 电平匹配
- 系统资源竞争
这些正是嵌入式开发的核心思维方式。
当你能在树莓派5上稳定地与GPS、LoRa、PLC、电机驱动器通过串口对话时,你就已经迈过了从“玩玩具”到“做产品”的门槛。
而这本该是一份手册就能教会你的事。
希望这篇指南能成为你工具箱里那张磨得发亮的接线图——每次遇到通信问题,翻出来一看,就知道该从哪里下手。
如果你正在做一个需要用串口连接外部设备的项目,欢迎在评论区留言交流。遇到了什么奇怪的现象?我们一起拆解。