3. Python 操作 GPIO:用 RPi.GPIO 库控制树莓派
好,咱们正式开始动手。这一章,我会带你用 Python 直接操作树莓派的 GPIO 引脚。说白了,就是让芯片的脚听你的话——输出高电平点亮 LED,或者读取按键按下时的电平变化。
我最早接触 RPi.GPIO 库时,觉得它就是个简单的开关控制。后来在项目中踩过几次坑,才发现里面的门道不少。比如中断触发抖动、引脚复用冲突,这些如果不注意,调试起来能让你怀疑人生。
咱们先搭好环境,然后一个一个功能过。
3.1 环境准备与库安装
树莓派上默认没有预装 RPi.GPIO,需要手动安装。我个人习惯用 pip3,干净利落。
sudo apt update
sudo apt install python3-pip
sudo pip3 install RPi.GPIO
装完之后,可以用 Python 交互式环境验证一下:
import RPi.GPIO as GPIO
print(GPIO.VERSION)
如果能打印出版本号,说明安装成功。嗯,这里要注意:如果你用的是树莓派 5,RPi.GPIO 可能不兼容,建议改用 gpiozero 或 librgpio。我在一次培训课上就遇到过学生拿 Pi 5 跑老代码,直接报错——硬件版本变了,库也得跟着升级。
3.2 GPIO 输出模式:点亮 LED
输出模式是最基础的操作。你想想看,控制一个 LED 亮灭,其实就是让引脚输出高电平(3.3V)或低电平(0V)。
先看电路连接:
| 元件 | 树莓派引脚 |
|---|---|
| LED 正极(长脚) | GPIO 17(物理引脚 11) |
| LED 负极(短脚) | GND(物理引脚 6) |
| 限流电阻(330Ω) | 串联在 LED 与 GPIO 之间 |
代码实现:
import RPi.GPIO as GPIO
import time
# 设置引脚编号模式
GPIO.setmode(GPIO.BCM) # 使用 BCM 编号
GPIO.setwarnings(False) # 关闭警告
# 设置 GPIO 17 为输出模式
LED_PIN = 17
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:
GPIO.cleanup() # 清理 GPIO 状态
个人经验:我习惯在代码开头加
GPIO.setwarnings(False),否则如果引脚之前被占用过,会一直弹警告。另外,GPIO.cleanup() 一定要在退出时调用,不然下次运行可能报错。
3.3 GPIO 输入模式:读取按键状态
输入模式用来检测外部信号,比如按键按下。这里有个关键点:按键按下时电平会抖动,硬件上需要加一个上拉或下拉电阻。
树莓派内部自带弱上拉电阻,我们可以直接启用:
BUTTON_PIN = 18
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
完整代码:
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)
try:
while True:
if GPIO.input(18) == GPIO.LOW: # 按键按下(低电平)
print("按键被按下")
else:
print("按键未按下")
time.sleep(0.1)
except KeyboardInterrupt:
GPIO.cleanup()
避坑指南:我曾经在项目中直接用
GPIO.input() 检测按键,结果发现按下一次会触发好几次。原因就是机械抖动。后来加了 20ms 的软件消抖才解决。后面讲中断时,我会专门演示消抖方法。
3.4 GPIO 中断:边沿触发事件检测
轮询方式(while 循环里不断读引脚)效率低,还占 CPU。更好的做法是用中断——引脚电平变化时,自动调用回调函数。
RPi.GPIO 支持三种边沿触发:
| 触发方式 | 说明 | 适用场景 |
|---|---|---|
GPIO.RISING | 上升沿触发(低→高) | 检测按键释放 |
GPIO.FALLING | 下降沿触发(高→低) | 检测按键按下 |
GPIO.BOTH | 双边沿触发 | 检测电平变化 |
代码示例:
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)
# 定义回调函数
def button_callback(channel):
print(f"引脚 {channel} 检测到下降沿,按键被按下")
# 注册中断
GPIO.add_event_detect(18, GPIO.FALLING,
callback=button_callback,
bouncetime=200) # 200ms 消抖
try:
print("等待按键中断...")
while True:
time.sleep(1) # 主程序可以干别的事
except KeyboardInterrupt:
GPIO.cleanup()
关键参数:
bouncetime 是硬件消抖时间,单位毫秒。我一般设 200ms,既能滤掉抖动,又不会让按键响应太迟钝。如果设得太小(比如 10ms),抖动还是会触发多次回调。
3.5 知识体系总览
下面这张图,把本章的核心逻辑串起来了。你可以把它当作操作 GPIO 的路线图:
3.6 常见问题与调试技巧
- 引脚编号混淆:BCM 编号和 BOARD 编号容易搞混。我建议统一用 BCM,因为大部分教程和库都默认 BCM。
- 中断不触发:检查回调函数是否注册成功。可以在回调里加个打印,看看到底有没有被调用。
- LED 不亮:先测引脚电压。用万用表量 GPIO 和 GND 之间,如果输出 HIGH 时电压接近 3.3V,说明代码没问题,检查电路。
- 按键误触发:bouncetime 设大一点。我试过 50ms 不够,200ms 基本稳。
调试小工具:我习惯在代码里加一个
GPIO.getmode() 打印当前模式,防止自己搞混。另外,用 gpio readall 命令可以查看所有引脚状态,非常直观。
好了,这一章的内容就这些。从输出到输入,再到中断,每一步都有对应的代码和电路。你可以在树莓派上直接跑一遍,看看效果。遇到问题别急,对照上面的表格和流程图,基本都能找到原因。