2026/10/6 9:12:09

树莓派GPIO基础入门:从引脚到Python点亮第一颗LED

树莓派GPIO基础入门:从引脚到Python点亮第一颗LED 我至今还记得第一次把杜邦线往树莓派GPIO排针上插时的忐忑金黄色的针脚密密麻麻排了两列每个针脚旁边没有丝印标注网上查来的引脚图要来回核对三四遍才敢接通电源。如果你也处在“树莓派买回来了系统也装好了但面对GPIO不知道从哪儿下手”的阶段那么这篇就是为你准备的。GPIOGeneral Purpose Input Output通用输入输出是树莓派和物理世界对话的窗口通过它你可以让LED按你的节奏亮灭、读取按键和传感器的状态、控制舵机和电机。这篇文章是树莓派学习系列第7篇我们一次性把GPIO基础捋清楚引脚布局、Python操作、输入输出、PWM以及我这些年踩过的坑。先从原理入手再上实操最后给一套可以直接抄的排查思路。这样即便你没学过电子电路也能在半小时内把第一颗LED点亮。1. GPIO到底是什么别把它想成神秘引脚1.1 输入输出每个引脚本质上是一个可编程的开关和电表很多初学者把GPIO想象成一种需要“驱动”或“协议”的东西其实没那么玄乎。GPIO的每一个引脚在芯片内部就是一组可以配置的寄存器。你把它配置成输出模式它就像一个小型开关由程序决定对外输出高电平3.3V还是低电平0V你把它配置成输入模式它就像一块电压表程序去读取这个引脚上当前是3.3V还是0V。这里有个关键点树莓派的GPIO输出的是3.3V不是5V。Arduino的引脚输出是5V很多新手把Arduino的习惯带过来直接用树莓派GPIO去驱动5V继电器模块或者给某个传感器供电结果轻则读不到信号重则烧掉引脚。后面我会专门讲电压和电流红线这里先记住这个核心差异。树莓派的Linux系统把所有GPIO都抽象成了文件或设备节点Python库又把这些节点封装成几个函数。所以你不用关心底层寄存器怎么操作但理解“输入/输出”的本质能帮你后续排查问题。另一个容易混淆的点是有些教程会提到“GPIO的8种工作模式”这个说法经常被搜索引擎归结到树莓派头上但严格说它来自STM32那类单片机的GPIO配置输入浮空、输入上拉、输入下拉、模拟输入、开漏输出、推挽输出、推挽复用、开漏复用。树莓派的Linux GPIO并没有暴露这么细的模式RPi.GPIO库一般只区分INPUT、OUTPUT、PWM、软件中断等。别被这个概念带偏先把最常用的输入和输出玩熟。1.2 40Pin排针先记住电源和地再记编号树莓派从1代到4代物理接口基本都保持40Pin排针早期的26Pin版本不算1代B之后都是40Pin。板子拿在手里让USB接口朝下、GPIO排针在右上角从左上角开始数靠近外侧的是第1针内侧是第2针一行行往下就是双排共40根针脚。这个物理编号叫BOARD编号从1到40。第一次接触时不要试图背下40个引脚只记几根关键针脚就够了第1针3.3V电源第2针、第4针5V电源第3、5、7、9等若干针GND地线剩下的大部分是GPIO引脚其中很多还复用I2C、SPI、UART等串行接口功能为了直观你把引脚图下载下来或者用pinout命令查看。在终端里输入pinout系统会直接打印出一张引脚功能图标注每个物理针脚的编号、BCM编号、I2C/SPI/UART复用功能。这个小工具比对着网上图片方便很多树莓派官方系统自带。我自己的经验是接线之前先用笔在纸上列出你本次要用哪几个引脚比如LED接GPIO 17按键接GPIO 27然后对照引脚图找到对应的物理针脚位置再动手插线。不要边插边想不然很容易错位。1.3 GPIO编号体系BCM和BOARD为什么让人头疼你会在所有树莓派教程里看到两种编号方式BOARD和BCM。BOARD编号就是物理针脚号码1到40从左上角一路排下来。BCM编号则是博通SoC内部的GPIO号比如GPIO 17在物理上对应第11针GPIO 27对应第13针。同一个引脚两个编号新手就在这上面栽跟头。举个例子在代码里写GPIO.setmode(GPIO.BCM)然后用GPIO.output(17, True)点亮的是物理第11针如果写的是GPIO.setmode(GPIO.BOARD)再用GPIO.output(11, True)效果相同。最典型的错误是模式设成BCM却把物理针脚号当参数传进去结果控制了一个完全不同的引脚板子没反应还以为是硬件坏了。我的建议是统一用BCM编号。原因有三第一绝大多数传感器示例代码都用BCM第二BCM编号和芯片数据手册对应查资料方便第三wiringPi编号在树莓派4B上已经基本没人用了没必要学。记住setmode必须在所有setup和output调用之前执行否则代码会报错提示你没有设置模式。2. 环境准备一条命令装库先跑通首个程序2.1 确保系统是官方系统Python版本不是障碍我默认你已经在树莓派上装好了官方系统不管是Raspberry Pi OS还是Ubuntu Server。树莓派官方系统通常自带Python 3版本在3.7到3.11不等这不重要因为我们要用的RPi.GPIO库是老牌库兼容性很稳定。唯一要确认的是系统能联网因为我们需要安装一个Python库。如果是在校学生用的是预装了系统的SD卡建议先跑一遍sudo apt update sudo apt upgrade把系统包更新干净再安装后面的库。这一步能减少很多莫名其妙的“Permission denied”和“ModuleNotFoundError”。顺便说一句直接连键盘显示器是最省事的操作方式。如果手里只有笔记本也可以通过SSH远程登录GPIO操作和本机执行没有任何区别。远程操作时需要注意如果程序在SSH会话里跑着只要那个会话一断程序就停了。想要断电后自动跑后面可以再学systemd服务或者cron本文先不展开。2.2 安装RPi.GPIO以及树莓派5的替代方案在终端里执行sudo apt update sudo apt install python3-pip sudo pip3 install RPi.GPIO有些预装系统可能已经包含了RPi.GPIO你可以先跑一句python3 -c import RPi.GPIO as GPIO; print(GPIO.VERSION)试试。如果输出版本号说明已经装了。这里要特别提醒如果你用的是树莓派5事情会有点不一样。树莓派5换用了RP1芯片来管理外设老牌的RPi.GPIO库官方已经明确不再适配树莓派5。在树莓派5上直接import RPi.GPIO会报错或者无法正常工作。社区给的替代方案有两个一个叫rpi-lgpio它把RPi.GPIO的API重新实现了一遍老代码基本不用改另一个叫gpiod是更接近Linux内核风格的库API更复杂但更正规。我建议树莓派5用户先装rpi-lgpiosudo pip3 install rpi-lgpio然后把import RPi.GPIO换成import lgpio as GPIO不对rpi-lgpio安装后依然提供RPi.GPIO模块名所以代码不用改。我自己实测时直接用import RPi.GPIO也能跑起来因为rpi-lgpio会注册兼容入口。如果你在树莓派5上遇到老代码报错优先尝试这个库。2.3 第一个程序点亮一颗外接LED硬件准备一颗普通发光二极管、一个220Ω到1kΩ的电阻、两根公母杜邦线。先把电阻串在LED的任意一端然后把电阻的另一端接到某个GPIO引脚我用BCM 17物理第11针LED的另一端接到GND。别看这个电路简单电阻不是可选项。后面我会详细说电阻的取值逻辑这里先按标准接法做。然后新建一个文件led_test.pyimport RPi.GPIO as GPIO import time LED_PIN 17 GPIO.setmode(GPIO.BCM) GPIO.setup(LED_PIN, GPIO.OUT) GPIO.output(LED_PIN, GPIO.HIGH) time.sleep(3) GPIO.cleanup()保存后运行python3 led_test.py你应该能看到LED亮3秒后熄灭。如果灯没亮不要急着怀疑代码先检查接线LED的极性对不对发光二极管长脚是阳极要接电阻后接到GPIO短脚是阴极接GND。如果接反了灯不会亮但通常不会烧东西。另外确认杜邦线有没有插到正确的物理针脚上我一再强调这一点因为太多的“程序没反应”最后都是接错针脚。2.4 代码逐行解释逐行看这段代码第一行导入RPi.GPIO模块并给它起了一个缩写叫 GPIO后面所有调用都基于这个别名。time用来延时。LED_PIN 17是我们选用的BCM引脚号等会儿换引脚只改这一行就行。GPIO.setmode(GPIO.BCM)告诉库我们使用BCM编号体系它决定了后面所有引脚号的意义。GPIO.setup(LED_PIN, GPIO.OUT)把该引脚设置为输出模式相当于把芯片内部的开关切换到输出挡位。GPIO.output(LED_PIN, GPIO.HIGH)输出高电平此时引脚对外是3.3V电流流过LED灯就亮了。time.sleep(3)保持这个状态3秒。最后的GPIO.cleanup()把引脚恢复为输入模式释放资源。有一个让很多人困惑的点为什么点亮LED后要延时再cleanup()因为如果不延时程序瞬间结束LED一亮就灭肉眼可能根本没看到。而cleanup()会把所有引脚恢复为输入模式相当于切断输出所以灯灭了。如果代码在最后没有cleanup()程序退出后引脚会保持你最后设置的电平状态灯会一直亮着。这既可能是好事也可能是坏事后面会专门讨论。3. 输出模式从“亮一下”到“按你的节奏闪烁”3.1 限流电阻怎么选不是随便一个电阻都行GPIO输出高电平时引脚上本质是输出一个3.3V的电压。如果直接把LED接到GPIO和GND之间LED正向导通电阻很小流过的电流会非常大轻则LED烧毁重则损坏树莓派的引脚。所以必须串联一个限流电阻。欧姆定律R (V_GPIO - V_LED) / I_LED。普通红色LED的正向压降大约1.8V到2.0V蓝白LED大约3.0V到3.3V工作电流一般取5mA到20mA。以红色LED、希望电流10mA计算R (3.3 - 1.9) / 0.01 140Ω。所以选220Ω到470Ω都没问题电流会偏小一些LED不会像手电筒那么亮但完全能看清而且对引脚更安全。我之前写过一版用100Ω电阻的代码灯是很亮但手指摸到电阻表面都能感觉到温升。后来统一改成330Ω安稳很多。记住树莓派单个GPIO最大安全输出电流大约是16mA不要超过这个值。如果你看到教程里有人直接不接电阻把LED接到GPIO上那是在燃烧板子的寿命。另外如果你要驱动继电器、电机、蜂鸣器这类大电流设备不能直接接GPIO必须通过三极管、MOS管或者专门的驱动模块。这一点我在后面的坑位章节会再强调。3.2 用循环写一个闪烁灯闪烁的本质就是让GPIO以一定时间间隔交替输出高电平和低电平。把刚才的代码稍作修改import RPi.GPIO as GPIO import time LED_PIN 17 GPIO.setmode(GPIO.BCM) GPIO.setup(LED_PIN, GPIO.OUT) try: while True: GPIO.output(LED_PIN, GPIO.HIGH) time.sleep(0.5) GPIO.output(LED_PIN, GPIO.LOW) time.sleep(0.5) except KeyboardInterrupt: pass finally: GPIO.cleanup()这次代码里加了try/except/finally。KeyboardInterrupt是当你按下CtrlC终止程序时抛出的异常except捕捉到之后跳过循环进入finally块执行GPIO.cleanup()。这样程序终止后LED会熄灭引脚不会在异常退出时保持高电平也方便下次运行。很多新手看到这个结构觉得多余直接写了while True没有异常处理结果程序一旦报错LED永远亮着引脚也被系统占用再运行程序就报RuntimeError: Port already in use。所以从第一课开始就养成try/except/finally的习惯能少踩很多坑。3.3 把LED控制封装成函数之后项目复用学到这里你可以把LED操作封装成一个小函数让代码更清晰import RPi.GPIO as GPIO import time def led_init(pin): GPIO.setmode(GPIO.BCM) GPIO.setup(pin, GPIO.OUT) def blink_led(pin, on_time0.5, off_time0.5, count10): for _ in range(count): GPIO.output(pin, GPIO.HIGH) time.sleep(on_time) GPIO.output(pin, GPIO.LOW) time.sleep(off_time)封装不是为了炫技而是当你手头有3个LED时不会在主程序里写20行重复的output调用。后面做智能小车、家居项目时这种小块函数都能直接复用。我自己的项目模板里都会放一个gpio_utils.py把LED、按键、蜂鸣器的基础操作都写进去。当然封装过度也不行项目大了之后直接用面向对象写硬件驱动类更合理。这篇先讲基础不展开。4. 输入模式与按键消抖读电平容易读“真”难4.1 浮空引脚为什么不能直接读输入模式的应用场景是读取外界状态比如按键是否被按下、传感器输出是高还是低。最简单的办法是读取引脚电平。先别急着写代码你要理解引脚悬空的问题。所谓悬空就是引脚没有接任何确定电压来源只接着一根杜邦线线的另一端悬在半空。此时你用GPIO.input(pin)去读读到的值是不确定的有时候是高有时候是低甚至手指靠近一点都会变。这是因为引脚自身有很高的输入阻抗周围电磁噪声很容易耦合进去。所以做输入检测时不能让引脚悬空必须通过一个电阻把它稳定在确定的电平上这个电阻就叫上拉电阻或下拉电阻。4.2 外部上拉/下拉和内部上拉怎么选先说外部上拉在GPIO引脚和3.3V之间接一个10kΩ电阻平时引脚被拉到高电平。当按键按下后引脚被按键接到GND电平变成低。这样程序读到低电平时就知道按键被按下了。如果把电阻接到GND就叫下拉电阻平时低电平按下后变成高电平程序就要反过来判断。树莓派内部其实已经集成了可配置的上拉/下拉电阻所以在RPi.GPIO中不需要外接电阻就能实现上拉效果GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_downGPIO.PUD_UP)这行代码把引脚配置成输入并启用内部上拉。此时按键的一端接GPIO引脚另一端接GND。平时引脚为高电平按下时引脚为低电平。用内部上拉的好处是省一个电阻坏处是内部上拉电阻的阻值很大大约50kΩ左右抗干扰能力不如外部10kΩ电阻。如果按键引线特别长或者环境里有大功率电机干扰建议用外部上拉电阻。另外有个初学者特别容易踩的点按键用内部上拉时另一端必须接GND不是接3.3V。如果按键另一端接到3.3V按下后引脚就变成高电平由于内部上拉也是高电平等于按键完全没作用。反过来如果启用内部下拉按键另一端要接3.3V。4.3 消抖按键按一下程序读成十下的原因机械按键在按下和松开的时候金属触点并不是一次性稳定接触而是会在几毫秒到几十毫秒内反复弹跳。你明明只按了一下程序可能读到几次甚至十几次电平跳变。如果不做消抖计数器会乱跳这是所有初学者都会遇到的现象。最简单的软件消抖是延时判断import RPi.GPIO as GPIO import time BUTTON_PIN 27 LED_PIN 17 GPIO.setmode(GPIO.BCM) GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_downGPIO.PUD_UP) GPIO.setup(LED_PIN, GPIO.OUT) while True: if GPIO.input(BUTTON_PIN) GPIO.LOW: time.sleep(0.05) # 跳过抖动窗口 if GPIO.input(BUTTON_PIN) GPIO.LOW: GPIO.output(LED_PIN, not GPIO.input(LED_PIN)) while GPIO.input(BUTTON_PIN) GPIO.LOW: time.sleep(0.1)这段代码做的逻辑是先读到低电平等待50毫秒如果50毫秒后还是低电平说明不是噪声确实是按键按下了。然后切换LED状态并检测按键是否松开防止一按下去就多次触发。50毫秒这个值是我的经验值。机械按键的抖动一般在10到20毫秒内结束取50毫秒已经有足够余量。要是你的按键接了一段很长的线抖动会更严重可以把延时调到100毫秒。但这种time.sleep消抖方式有个缺陷延时期间程序是阻塞的其他任务都停了。如果项目里同时要处理多个按键或者要控制多个LED闪烁阻塞式消抖会让系统显得卡顿。更专业的做法是用状态机或者边沿检测后续可以单独写一篇这里先把最基础的做法吃透。5. PWM呼吸灯、舵机和调光的基础5.1 占空比与频率PWM不是模拟电压PWM的全称是脉宽调制简单说就是让引脚以极高的频率在高低电平之间切换。LED看到的不是一个稳定的3.3V而是一串方波。人眼有视觉暂留效应只要切换频率够高看到的就是一个亮度固定的灯。改变高电平在一个周期内占的比例也就是占空比就能改变亮度。举例周期是10毫秒其中高电平占3毫秒、低电平7毫秒占空比就是30%。LED亮度大约只有最大亮度的30%。如果高电平占8毫秒占空比80%灯就明显更亮。这里必须澄清一个概念PWM不是模拟电压虽然两者最终效果在某些场合看起来一样但本质上一个持续输出2.4V的电源和一个以80%占空比高速切换的3.3V方波在电气特性上是完全不同的。LED可以用PWM电机可以用PWM但如果你要驱动一个需要精确模拟电压的电路不能直接拿PWM输出接上去后面要加滤波器。5.2 用RPi.GPIO控制PWM输出RPi.GPIO里的PWM使用非常简单import RPi.GPIO as GPIO import time LED_PIN 17 GPIO.setmode(GPIO.BCM) GPIO.setup(LED_PIN, GPIO.OUT) pwm GPIO.PWM(LED_PIN, 50) # 50Hz频率 pwm.start(0) # 初始占空比0% for duty in range(0, 101, 5): # 从0到100步进5 pwm.ChangeDutyCycle(duty) time.sleep(0.05) time.sleep(1) for duty in range(100, -1, -5): pwm.ChangeDutyCycle(duty) time.sleep(0.05) pwm.stop() GPIO.cleanup()这段代码实现了呼吸灯效果LED先慢慢变亮再慢慢变暗。50Hz是电源频率附近人眼基本感觉不到闪烁。有些对闪烁敏感的人可能还是能察觉可以提高到1kHzLED表现更稳定。注意RPi.GPIO的PWM是软件PWM启动后依赖于系统调度如果你同时跑很多程序PWM波的抖动会变大。如果项目对PWM频率精度要求很高比如舵机控制推荐用树莓派硬件PWM或者干脆换树莓派Pico。但基础学习和普通调光软件PWM足够了。5.3 从呼吸灯到舵机PWM的典型应用边界舵机是PWM应用的经典场景。标准舵机接收的PWM信号频率是50Hz整整20毫秒为一个周期高电平脉冲宽度通常从0.5毫秒到2.5毫秒对应舵机从0度转到180度。把50Hz和0.5ms到2.5ms结合来看占空比大约在2.5%到12.5%之间。所以控制舵机不是简单地设置一个占空比而是要根据脉宽换算。这里有个容易忽略的坑树莓派的GPIO逻辑电平是3.3V但很多常见的SG90舵机标称工作电压是4.8V到6V它的信号线也经常被设计成5V逻辑。直接用树莓派3.3V GPIO信号去控制5V供电的舵机大多数情况下能工作因为舵机芯片的输入高电平阈值没有那么高。但稳妥起见最好用电平转换模块或确认舵机兼容3.3V逻辑。反过来绝对不能把舵机的5V电源接到树莓派GPIO上给系统供电舵机瞬间电流可以到几百毫安甚至更高会把树莓派搞重启甚至烧掉。舵机要单独用外部5V电源并且电源地要和树莓派的地线共地否则信号参考电位不一致舵机就不受控。5.4 树莓派Pico和标准树莓派的PWM差异搜索树莓派相关内容时你经常会看到“树莓派Pico控制舵机”这种题目。Pico是树莓派家族里的微控制器开发板不是标准树莓派单板计算机它的GPIO操作方式和本篇讲的标准树莓派完全不同。Pico用的是MicroPython或C语言没有Linux系统GPIO控制更接近单片机PWM精度也比标准树莓派的软件PWM高得多。如果你只是想做一个小型、低功耗、实时的硬件控制项目Pico反而比标准树莓派更适合成本也低很多。但如果你需要同时跑摄像头、网络、数据库这些Linux服务双系统协同才是更优解。Pico的具体玩法可以留到系列后续再单独拆解这里先把标准树莓派的GPIO基础打牢。6. 综合练习做一个按键控制亮灭的智能小夜灯6.1 硬件连接理论学再多不如动手做一个能用的东西。这个综合小项目很简单一个按键控制LED的亮灭按一下亮再按一下灭。硬件清单树莓派任意型号、一个LED、一个330Ω电阻、一个轻触按键、若干杜邦线。连接方式如下LED阳极长脚通过330Ω电阻接到BCM 17物理第11针阴极接GND按键一端接BCM 27物理第13针另一端接GND不需要外接上拉电阻因为代码里启用内部上拉接线前先断电或者至少确认不会误碰其他引脚。我习惯在板子通电的情况下接线但每次都要非常小心避免杜邦线搭到5V和3.3V之间造成短路。如果你是新手建议给板子断电再插线插完后检查一遍再通电。6.2 软件逻辑完整代码如下它结合了输出、输入、内部上拉和消抖import RPi.GPIO as GPIO import time LED_PIN 17 BUTTON_PIN 27 GPIO.setmode(GPIO.BCM) GPIO.setup(LED_PIN, GPIO.OUT) GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_downGPIO.PUD_UP) led_state GPIO.LOW try: while True: if GPIO.input(BUTTON_PIN) GPIO.LOW: time.sleep(0.05) if GPIO.input(BUTTON_PIN) GPIO.LOW: led_state not led_state GPIO.output(LED_PIN, led_state) while GPIO.input(BUTTON_PIN) GPIO.LOW: time.sleep(0.1) except KeyboardInterrupt: pass finally: GPIO.cleanup()注意看按键检测逻辑里的第二个while它一直等到按键松开才继续判断下一次按键。这样设计是为了防止长按按键时LED反复切换。如果你希望实现“按住点动”效果可以把这行去掉改成按键按下时LED亮、松开时LED灭那是另一种玩具玩法。运行这段代码按下按键LED应该切换状态。如果按键不灵敏多半是消抖时间不够把0.05改成0.08试试。如果LED不亮就用万用表量一下GPIO 17有没有3.3V输出。没有万用表的话先用前面学过的点亮LED测试代码单独验证硬件是否正常逐段缩小问题范围。6.3 试试改进方向这个小项目做完你已经掌握了GPIO最核心的输入输出能力。在此基础上可以做很多扩展把LED换成有源蜂鸣器模块的地线接GND信号线接GPIO就能做按键门铃加两个LED配合红绿灯逻辑做一个简单交通灯演示按键长按和短按区分处理也就是在消抖后继续计时检测按下时长这能在同一个按键上实现不同功能用PWM控制LED亮度让按键每按一次亮度提升一档我一直觉得学习硬件编程最好的路径就是“先做个能亮的东西再在它旁边加功能”。一开始不用追求复杂的传感器把输出和输入这两种最基础的模式玩透之后读温度传感器、接超声波模块都会水到渠成。7. 新手最容易遇到的GPIO坑与排查方法7.1 引脚烧毁的常见原因GPIO引脚烧毁通常是电流过大或电压超限。树莓派GPIO虽然内部有保护电路但不要把它当成金刚不坏之身。最容易出问题的操作如下直接把LED接到GPIO和3.3V之间而不接电阻用GPIO直接驱动继电器线圈或直流电机把5V电源接到3.3V的GPIO引脚上将两个GPIO输出引脚短接在一起一个输出高电平另一个输出低电平会形成直通电流其中把5V接到GPIO引脚上是杀伤力最大的。树莓派的引脚对3.3V以上的电压非常敏感5V信号进入GPIO会直接击穿引脚内部的保护二极管。如果你要接5V逻辑的设备务必用双向电平转换模块。如果真的烧坏了引脚通常不是整个树莓派报废而是某个或者某几个GPIO通道损坏。树莓派上的损坏是不可逆的只能绕开这些引脚换用别的GPIO。我自己的板子就烧过一个引脚后来一直用一个“禁用了坏引脚”的脚本做保护。当然最稳妥防烧的办法是接一个GPIO保护扩展板几十块钱能省下换板子的钱。7.2 GPIO.cleanup()不能乱写的原因前面代码里几乎每次都在最后调用GPIO.cleanup()它会把所有GPIO恢复为默认输入状态。这在开发阶段很方便但也有个坑当你的程序已经调用cleanup()后如果之后又尝试操作某个引脚会报错或直接跳过。更麻烦的是如果你同时运行两个操作GPIO的Python程序一个程序执行了cleanup()会把另一个程序初始化的引脚也重置掉导致另一个程序莫名其妙失效。正确的做法是只在程序退出时调用cleanup()并且尽量只清理自己用的引脚。比如可以写成GPIO.cleanup([LED_PIN, BUTTON_PIN])只传引脚列表这样不会影响其他程序。如果程序需要长时间运行比如服务器则一般不主动调用cleanup()让它保持初始化状态即可。7.3 程序假死、权限不足、引脚被占用刚接触GPIO时你是不是遇到过这种情况程序运行后看起来就像卡住了键盘CtrlC也没反应。这多半不是树莓派死机而是你的GPIO程序进入了死循环同时异常处理没写好导致无法正常退出。可以另开一个SSH终端执行sudo pkill -f 你的脚本名.py把进程杀掉。如果是因为GPIO引脚被前一个没退干净的程序占用重启一下Python进程通常能解决终极办法是重启树莓派。另一个常见错误是RuntimeError: Not running as root。旧版RPi.GPIO库在某些系统上需要root权限访问 /dev/mem 或 /dev/gpiomem默认用户没有权限。解决办法是执行程序时加sudo或者把自己的用户加入gpio组。不过官方Raspberry Pi OS较新版本已经把 /dev/gpiomem 的权限放开了普通用户可以直接访问GPIO一般不需要sudo。如果你在Ubuntu上遇到权限问题加sudo是最快的办法。引脚被占用时通常会报RuntimeError: Port already in use或者类似的“gpio busy”错误。排查时可以执行gpio readall如果安装了wiringPi或者pinctrl get 17查看引脚当前状态。更好的习惯是在写代码前先检查有没有其他进程占用你计划使用的引脚。7.4 排查问题的小工具GPIO问题排查我最常用的顺序是用pinout命令确认引脚位置用python3 -c import RPi.GPIO as GPIO; GPIO.setmode(GPIO.BCM); GPIO.setup(17, GPIO.OUT); GPIO.output(17, GPIO.HIGH)快速测试引脚是否能输出高电平用万用表量引脚和GND之间是否有3.3V检查接线图有没有接错特别是电源和地的位置写出最小化测试代码排除业务逻辑干扰如果你没有万用表可以外接一个带指示灯的模块比如LED模块直接看是否有电压输出。这个方法简单粗暴但确实能帮你快速区分“程序问题”和“硬件问题”。还有一个实用工具是pinctrl树莓派官方系统自带可以查看和修改引脚复用状态。比如pinctrl get 17能显示第17号引脚的当前功能和电平。这个工具比直接看电气图直观在排查引脚被复用为其他功能时特别管用。回看我最早学树莓派GPIO的经历真正让人进步的并不是记住某个函数而是日常积累下来的这些“为什么”。为什么这个灯要接电阻为什么按键要上拉为什么程序退出要cleanup。搞清楚这些底层逻辑后面学任何传感器、任何外设模块都能触类旁通。如果你照着这篇文章把LED和按键的例子跑通了GPIO基础这一关就算过了接下来可以去碰I2C、SPI这些串行协议也可以回头研究树莓派小车这类综合项目。希望这篇能帮你少烧几块板子多找点乐趣。