手把手教你用Python玩转树莓派5:从点亮LED到响应按钮的完整实战
你有没有想过,一块信用卡大小的电脑,不仅能上网、跑系统,还能直接控制现实世界里的灯、电机、传感器?这正是树莓派的魅力所在。
而这一切的起点,就是那排不起眼的40针引脚——它们是树莓派与物理世界对话的“神经末梢”。今天我们就以树莓派5为平台,带你用最经典的RPi.GPIO库,从零开始实现硬件交互,不绕弯子,直接上手。
为什么还在用 RPi.GPIO?
你可能听说过,官方推荐使用更新的gpiozero或lgpio。没错,这些库在多线程和稳定性上更胜一筹。但对初学者来说,RPi.GPIO依然是最好的“第一课”:
- 语法极简:几行代码就能点亮LED
- 资料海量:网上90%的教程都基于它
- 逻辑清晰:没有过多封装,能看清底层控制流程
更重要的是,它是理解GPIO本质的“透明窗口”。等你熟悉了它,再升级也不迟。
✅ 提示:本文所有代码均在树莓派5 + Raspberry Pi OS(64位)实测通过。
先搞清一件事:BCM 和 BOARD 编号有什么区别?
新手最容易踩的坑,就是接错了引脚。关键就在于搞懂两种编号方式:
| 类型 | 含义 | 特点 |
|---|---|---|
GPIO.BCM | 芯片级编号(Broadcom SoC 引脚号) | 推荐使用,与数据手册一致 |
GPIO.BOARD | 物理引脚顺序(从1到40) | 直观,但不反映芯片逻辑 |
举个例子:
你想控制物理第12号引脚(靠近USB口那一排的第6个),它对应的是GPIO18。
所以你应该写:
GPIO.setmode(GPIO.BCM) LED_PIN = 18 # 不是12!📌记住口诀:编程用 BCM,查板看 BOARD。
实战1:让LED闪烁起来(输出控制)
这是嵌入式的“Hello World”。我们来写第一个程序——让一个LED以1秒频率闪烁。
硬件连接
- LED正极 → 限流电阻(220Ω)→ GPIO18(物理引脚12)
- LED负极 → GND(物理引脚14)
⚠️ 务必加电阻!否则可能烧毁GPIO或LED。
代码实现
import RPi.GPIO as GPIO import time # 设置为BCM编号模式 GPIO.setmode(GPIO.BCM) # 定义引脚 LED_PIN = 18 GPIO.setup(LED_PIN, GPIO.OUT) try: while True: GPIO.output(LED_PIN, GPIO.HIGH) # 高电平:灯亮 time.sleep(1) GPIO.output(LED_PIN, GPIO.LOW) # 低电平:灯灭 time.sleep(1) except KeyboardInterrupt: print("\n程序被用户中断") finally: GPIO.cleanup() # 关键!释放引脚资源关键点解析
GPIO.setup(pin, direction):配置引脚为输入或输出GPIO.output(pin, level):写入高/低电平GPIO.cleanup():退出前必须调用,否则下次运行会报错:“This channel is already in use”
💡 小技巧:可以把延时改成0.1秒,看看LED是不是变成了“呼吸灯”效果?
实战2:读取按钮状态(输入检测 + 上拉电阻)
现在我们反过来,让树莓派“感知”外部操作。按下按钮,LED亮起。
硬件连接
- 按钮一脚 → GPIO16(物理引脚36)
- 按钮另一脚 → GND
- LED仍接GPIO18
不需要外接上拉电阻!树莓派支持内部启用。
代码实现
import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) BUTTON_PIN = 16 LED_PIN = 18 # 配置输入,并启用内部上拉电阻 GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(LED_PIN, GPIO.OUT) try: while True: # 按钮未按下时为 HIGH,按下后接地变为 LOW if GPIO.input(BUTTON_PIN) == GPIO.LOW: GPIO.output(LED_PIN, GPIO.HIGH) print("按钮已按下") else: GPIO.output(LED_PIN, GPIO.LOW) time.sleep(0.1) # 简单防抖 except KeyboardInterrupt: pass finally: GPIO.cleanup()为什么需要上拉电阻?
如果不加上拉,引脚处于“悬空”状态,电压不稳定,读数会随机跳变。启用PUD_UP后,默认为高电平,只有按下时才被拉低,信号干净可靠。
🔧 防抖说明:机械按钮在按下瞬间会有微小震动,导致多次触发。这里用time.sleep(0.1)做简单延迟过滤,工业场景建议结合硬件RC滤波或更复杂的软件算法。
实战3:事件驱动——不再轮询,而是“被通知”
上面的例子中,程序一直在循环里问:“按了吗?按了吗?”效率很低。有没有办法让它“等通知”?
有!这就是边沿检测(Edge Detection),类似操作系统里的中断机制。
改进版:异步响应按钮
import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) BUTTON_PIN = 16 GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP) def on_button_pressed(channel): print(f"🎉 按钮在通道 {channel} 上被按下!") # 添加下降沿检测,触发回调函数 GPIO.add_event_detect( BUTTON_PIN, GPIO.FALLING, # 下降沿:从高变低 callback=on_button_pressed, bouncetime=200 # 去抖时间,单位毫秒 ) try: print("正在监听按钮... 按 Ctrl+C 退出") while True: time.sleep(1) # 主线程可以做其他事 except KeyboardInterrupt: pass finally: GPIO.cleanup()这样做的好处
- CPU不用频繁轮询,节省资源
- 响应更快,尤其适合紧急停止、报警等场景
- 主程序可并发处理其他任务(比如采集传感器数据)
🧠 思考:如果同时接了多个按钮,都能用同一个回调函数吗?答案是能!channel参数会告诉你具体是哪个引脚触发的。
树莓派5引脚图:一张表说清所有功能
别再每次去翻官网了,下面是树莓派5 40针引脚的核心信息浓缩版:
| 物理引脚 | BCM编号 | 功能 | 备注 |
|---|---|---|---|
| 1 | - | 3.3V电源 | 最大供电50mA |
| 2 | - | 5V电源 | 来自USB-C,最大可输出约1A(带限流保护) |
| 6 | - | GND | 接地 |
| 3 | GPIO2 | I²C SDA | 接OLED、温湿度传感器 |
| 5 | GPIO3 | I²C SCL | 同上 |
| 8 | GPIO14 | UART TX | 串口输出 |
| 10 | GPIO15 | UART RX | 串口输入 |
| 19 | GPIO10 | SPI MOSI | 主出从入 |
| 21 | GPIO9 | SPI MISO | 主入从出 |
| 23 | GPIO11 | SPI SCLK | 时钟线 |
| 24 | GPIO8 | SPI CE0 | 片选0 |
| 7 | GPIO4 | 通用GPIO | 常用于DS18B20 |
| 12 | GPIO18 | PWM输出 | 支持硬件PWM,可用于电机调速 |
🔋 电源提示:
- 3.3V引脚由板载LDO稳压器提供,总电流有限,不要接太多外设
- 5V引脚来自输入电源,可用于驱动继电器、风扇等大功率设备⚠️ 安全警告:
所有GPIO引脚仅支持3.3V电平,严禁接入5V信号!否则可能导致芯片损坏!
电气参数你必须知道的几个数字
很多项目失败,不是代码问题,而是忽略了硬件限制。以下是关键参数:
| 参数 | 数值 | 说明 |
|---|---|---|
| 单引脚最大输出电流 | 16mA | 驱动LED没问题,但别想直接驱动继电器 |
| 所有GPIO总输出电流 | ≤50mA | 建议控制在30mA以内更安全 |
| 输入高电平阈值 | >2.0V | 低于此值可能识别为LOW |
| 输入低电平阈值 | <0.8V | 高于此值可能误判为HIGH |
| 内部上拉电阻 | ~50kΩ | 较弱,长距离传输需外加强上拉 |
📌 实践建议:
- 驱动蜂鸣器、继电器、电机时,请使用三极管或光耦隔离
- 使用I²C时,在SDA/SCL线上各加一个4.7kΩ上拉电阻到3.3V(虽然内部有,但外接更稳定)
- 多个设备共用I²C总线时,用i2cdetect -y 1命令扫描地址是否冲突
工程最佳实践:别让项目变成“火柴盒”
当你从小实验迈向真实项目时,以下几点能帮你少走弯路:
1. 每次都清理引脚
finally: GPIO.cleanup()这条语句不是可选项。忘记它,下次运行就会遇到恼人的“Channel already in use”错误。
2. 用面包板测试,别直接焊
先用跳线+面包板验证逻辑,确认无误后再焊接。一次短路可能让你换一块树莓派。
3. 合理规划复用引脚
某些引脚具有特殊功能(如PWM、SPI),优先将这类功能分配给专用引脚。例如:
- PWM调光 → GPIO12/13/18/19
- I²C通信 → GPIO2/3(默认启用)
- UART调试 → GPIO14/15(注意占用串口)
4. 新项目考虑gpiozero
虽然本文用了RPi.GPIO,但对于新项目,尤其是涉及按钮、LED、电机等常见组件时,gpiozero更简洁:
from gpiozero import LED, Button from signal import pause led = LED(18) btn = Button(16) btn.when_pressed = led.on btn.when_released = led.off pause() # 保持运行代码减半,功能相同,还自带去抖和事件处理。
结尾:这只是开始
你现在已经掌握了如何用Python操控树莓派5的引脚——从最基本的输出控制,到输入检测,再到事件驱动编程。但这只是智能硬件世界的入口。
接下来你可以尝试:
- 连接DHT11温湿度传感器,把数据打印出来
- 用PWM控制LED亮度,做出呼吸灯效果
- 接一个I²C OLED屏幕,显示实时信息
- 把按钮事件通过MQTT发到手机
甚至把整个系统封装成Web服务,用Flask做个远程开关面板。
💬 如果你在接线或运行中遇到了问题,欢迎留言交流。每一个“灯没亮”的背后,都藏着一个值得解决的技术细节。
现在,去点亮你的第一盏灯吧。