news 2026/9/6 1:44:11

树莓派 Pico GPIO 完全指南:引脚映射、MicroPython 编程与实战避坑

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
树莓派 Pico GPIO 完全指南:引脚映射、MicroPython 编程与实战避坑

1. Pico 引脚布局与 GPIO 映射:先搞清楚物理引脚和编号的关系

拿到树莓派 Pico,第一眼看到的是那块长条形的开发板,两侧各有 20 个金属引脚,总共 40 个物理引脚。这块板子本身的尺寸和一块口香糖差不多,引脚却藏着不少门道。新手最容易踩的坑就是把物理引脚编号和 GPIO 编号搞混。

Pico 板上的引脚分三类信号:电源引脚(3V3、5V、GND)、控制引脚(GP0~GP28)、以及几个特殊功能引脚(如 ADC_VREF、AGND、RUN)。很多人以为板子上丝印标注的数字就是 GPIO 编号,其实不然。Pico 的丝印标注的是物理引脚序号,从 1 到 40,而 MicroPython 里操作时用的是 GPIO 编号。

我整理了一张对应关系表,方便你速查:

物理引脚GPIO 编号说明
1GP0通用输入输出,可复用 PWM/ADC
2GP1通用输入输出,可复用 PWM/ADC
4GP2通用输入输出
6GP3通用输入输出
9GP4通用输入输出
11GP5通用输入输出,SPI 片选
14GP6通用输入输出
16GP7通用输入输出
21GP16通用输入输出
24GP18通用输入输出
26GP20通用输入输出
31GP26ADC0 专用输入
32GP27ADC1 专用输入
34GP28ADC2 专用输入

板子右上角那颗小小的板载 LED,接在 GP25 上。调试时想快速验证代码能不能跑,直接操作这颗 LED 就是最快的方案,不需要接任何外部元器件。

还有一点必须说明:Pico 的 GPIO 电平是 3.3V,不是 5V。如果你以前玩过 Arduino,习惯了 5V 逻辑电平,换到 Pico 上直接驱动 5V 器件,轻则读不到高电平,重则烧毁引脚。往 GPIO 上接外部模块时,先确认模块是否兼容 3.3V 逻辑电平。

2. machine.Pin 类核心方法:构造、模式、读写究竟怎么用

在 MicroPython 中,操作 GPIO 的统一入口就是machine.Pin类。理解了这个类的设计思路,后面写再复杂的控制逻辑都能举一反三。

2.1 构造一个 Pin 对象:必须搞懂的 id、mode、pull

创建一个 Pin 对象的基本语法如下:

from machine import Pin # 最基本的形式:只指定引脚编号,默认输出模式 led = Pin(25, Pin.OUT) # 完整形式:指定编号、模式、默认电平、上下拉电阻 btn = Pin(16, Pin.IN, Pin.PULL_UP)

这里有两个关键参数:modepull

mode只有Pin.OUTPin.IN两种取值,分别对应输出模式和输入模式。Pico 的每个 GPIO 引脚内部结构决定了它同一时刻只能作为一种模式工作,你想让它既读又写(比如读取按键的同时驱动 LED),那需要两个不同的 Pin 对象,或者用复用功能。

pull参数只在输入模式下有意义,它控制引脚内部的上拉或下拉电阻。Pico 内部集成了可编程的上拉/下拉电阻,取值为Pin.PULL_UPPin.PULL_DOWNNone(默认,不启用内部电阻)。这个设计很实用,比如接一个按键到 GND 和某个 GPIO 之间,只需要启用内部上拉,按键未按下时读到高电平,按下时读到低电平,完全不需要外部电阻。

2.2 输出模式:value、toggle、高低电平的底层逻辑

创建了输出模式的 Pin 对象后,最常用的方法就是value()。这个方法有两种角色:无参数调用时是读取引脚当前电平,有参数调用时是设置引脚输出电平

from machine import Pin import time led = Pin(25, Pin.OUT) # 设置 LED 亮 led.value(1) # 等效于 led.on() time.sleep(1) # 设置 LED 灭 led.value(0) # 等效于 led.off() time.sleep(1) # 翻转电平 led.toggle()

value(1)会让引脚输出高电平,value(0)输出低电平。另外还有on()off()两个简写方法,逻辑语义更清晰:on()对应高电平,off()对应低电平。

toggle()方法没有参数,每次调用把当前电平取反。这个在闪烁灯、状态机切换场景里非常方便,省去了先读再写的操作。

底层来看,value(1)的本质是把引脚的输出数据寄存器对应位写 1,电平转换时间在微秒级。Pico 主频 133MHz,一次电平翻转大概需要 7 个时钟周期左右,也就是约 50 纳秒。这个速度对大多数传感器读取、LED 控制、继电器开关绰绰有余,但如果你要做高速 PWM 输出或者精确时序通信,建议直接用硬件外设(PWM、SPI、I2C),而不是靠手动翻转 GPIO。

2.3 输入模式:读取外部信号的关键细节

把引脚配置为输入模式后,核心方法是value(),它返回 0 或 1。但在实际使用中,有几个绕不开的细节:

悬空引脚的问题。如果你把引脚配置为输入模式,既不用上拉也不用下拉,引脚就处于高阻态。这时读取到的电平完全取决于外部环境——可能受旁边的走线干扰,也可能受手指触摸影响,结果不稳定。所以读取外部信号前,要么启用内部上拉/下拉,要么外部接电阻,确保引脚电平是确定的。

按键消抖。机械按键在按下和释放的瞬间,触点会产生 10~20ms 的抖动,电平在这段窗口内会快速跳变多次。如果不做消抖处理,一次按键可能被误判成多次。常见的软件消抖思路是延时后再确认一次:

from machine import Pin import time btn = Pin(16, Pin.IN, Pin.PULL_UP) led = Pin(25, Pin.OUT) while True: if btn.value() == 0: # 检测到按下 time.sleep_ms(10) # 延时避开抖动窗口 if btn.value() == 0: # 再次确认确实按下 led.toggle() while btn.value() == 0: # 等待松开 time.sleep_ms(10)

这种"检测-延时-再检测"的消抖方式,原理简单且足够应对大部分场景。更精细的做法是用定时器定期采样引脚状态,结合状态机判断按键事件,但对普通项目来说,第一种方案已经够用了。

3. GPIO 的 8 种工作模式:从原理到选择

标题提到 GPIO 的 8 种工作模式,这是从 STM32 那套体系里流传出来的概念。在 STM32 中,GPIO 可配置为输入浮空、输入上拉、输入下拉、模拟输入、开漏输出、推挽输出、复用开漏输出、复用推挽输出这 8 种模式。Pico 的 machine.Pin 并没有完全照搬这 8 种模式,但理解这些模式可以帮助你更好地理解外设接口设计。

Pico 的 MicroPython 固件中,Pin 类支持的模式其实就两种:Pin.INPin.OUT,但结合上下拉电阻和复用功能,可以模拟出类似的效果。对应关系大致如下:

STM32 模式Pico 等价实现典型应用场景
输入浮空Pin.IN(不启用上拉/下拉)外部已接上拉/下拉电阻的信号读取
输入上拉Pin.IN, Pin.PULL_UP按键到 GND 读取
输入下拉Pin.IN, Pin.PULL_DOWN按键到 3.3V 读取
模拟输入machine.ADC类而不是 Pin 类模拟电压采样
推挽输出Pin.OUTLED 驱动、电平输出
开漏输出Pin.OUT不直接支持,需外部上拉I2C 总线、电平转换
复用推挽输出由外设驱动(如 PWM、SPI)波形输出、通信协议
复用开漏输出I2C 外设自动配置I2C 通信

模式选择的判断逻辑其实很简单:这个引脚是负责读外部信号还是输出控制信号?读的话,外部信号是主动拉高拉低还是需要内部电阻帮忙确定电平?输出的话,是驱动常规数字器件还是需要开漏结构?

开漏输出这点值得展开说。开漏输出的特点是:引脚只能主动拉低到 GND,无法主动输出高电平。高电平必须靠外部上拉电阻提供。这种设计特别适合两个场景:I2C 总线的线与逻辑,以及不同电压域之间的电平转换。

Pico 的 machine.Pin 没有直接暴露开漏模式,但 MicroPython 固件内部用 I2C 外设时会自动把 SDA/SCL 配置为开漏结构,不需要你手动干预。如果你非要用普通 GPIO 模拟开漏效果,也不是不行,但效率很低不推荐。

4. 从 LED 到按钮:一个完整的气象站示例串联全部知识点

前面讲了一堆零散的知识点,现在用一个完整的实例把它们全部串起来感受一下。假设你要做一个室内气象站,功能是:

  • 用 DHT11 温湿度传感器读取温度和湿度
  • 用两个按键切换显示模式
  • 通过 I2C 接口的 OLED 屏幕显示数据
  • LED 在数据更新时闪烁一次作为反馈

这个项目会用到 GPIO 的输入模式(按键)、输出模式(LED)、以及两个复用功能(I2C 的 SDA/SCL 引脚)。接线方案如下:

外设引脚GPIO
DHT11 数据引脚物理引脚 4GP2
按键1物理引脚 16GP16
按键2物理引脚 18GP17
OLED SDA物理引脚 21GP16? 不对,是 GP16 已被按键占用

看完上面这段你可能已经警觉了:GP16 被按键占用了,OLED 该接哪里?Pico 的 I2C 外设支持多个引脚组合,常用的有 GP0/GP1、GP4/GP5、GP18/GP19。选择 GP4(物理引脚 6)和 GP5(物理引脚 7)作为 SDA 和 SCL,按键改接 GP16 和 GP17。

完整代码如下:

from machine import Pin, I2C, ADC import dht import time # 输出模式:板载 LED led = Pin(25, Pin.OUT) # 输入模式:两个按键,启用内部上拉 btn1 = Pin(16, Pin.IN, Pin.PULL_UP) btn2 = Pin(17, Pin.IN, Pin.PULL_UP) # DHT11 数据引脚 sensor = dht.DHT11(Pin(2)) # I2C 初始化,GP4=SDA, GP5=SCL i2c = I2C(0, scl=Pin(5), sda=Pin(4), freq=400000) # OLED 驱动 from ssd1306 import SSD1306_I2C oled = SSD1306_I2C(128, 64, i2c) display_mode = 0 # 0:温度 1:湿度 while True: try: sensor.measure() temp = sensor.temperature() hum = sensor.humidity() # 数据更新,LED 闪烁一次 led.value(1) time.sleep_ms(50) led.value(0) # 按键切换显示模式 if btn1.value() == 0: time.sleep_ms(20) if btn1.value() == 0: display_mode = 0 if btn2.value() == 0: time.sleep_ms(20) if btn2.value() == 0: display_mode = 1 # OLED 显示 oled.fill(0) if display_mode == 0: oled.text("Temp: {} C".format(temp), 0, 0) else: oled.text("Humidity: {}%".format(hum), 0, 0) oled.show() except Exception as e: print("Error:", e) time.sleep_ms(1000)

这个项目的价值在于把输入输出、复用功能、消抖、外设驱动全部整合在一起。后面做更复杂的项目,无非是在这个框架上增加更多外设,但 GPIO 操作的底层逻辑完全一致。

5. 实战避坑:程序反复报错的常见常见问题排查

第一次上手 Pico GPIO 的人,十个里有八个会在下面这些问题上卡壳。我把踩过的坑按频率排了个序,你对照着排查能省不少时间。

坑一:引脚的编号写错。GPIO 编号不是物理引脚序号。GP0 对应物理引脚 1,GP1 对应物理引脚 2,GP2 对应物理引脚 4。物理引脚 3、5、7 这些奇数编号都是 GND 或电源引脚,不是 GPIO。新手最容易犯的错误是把物理引脚 3 当 GP3 用,实际上 GP3 是物理引脚 5。

坑二:忘了 Pico 是 3.3V 逻辑电平。驱动 5V 继电器模块、5V LED 灯带这类设备,直接用 GPIO 引脚接过去就是自寻短路。解决办法是加电平转换模块,或者用光耦隔离。

坑三:输入悬空导致误触发。按键、传感器这类输入引脚,必须在软件上启用内部上拉或下拉,否则引脚电平漂浮不定,读到的数据毫无意义。

坑四:ADC 引脚当成普通 GPIO。GP26、GP27、GP28 这 3 个引脚既是普通 GPIO,也是 ADC 通道。但 ADC 输入电压范围是 0~3.3V,超过这个范围必须分压,否则直接烧毁引脚。

坑五:PWM 和中断的引脚冲突。Pico 虽然每个引脚几乎都支持 PWM,但同一时刻一个引脚只能承担一种复用功能。如果代码里先初始化 PWM,又尝试在这个引脚上读取中断触发,大概率会得到不符合预期的行为。

坑六:MicroPython 里没有GPIO.setmode()之类的函数。按照 Arduino 和 STM32 的惯性,很多人想知道如何配置引脚模式。在 MicroPython 中,创建 Pin 对象时直接指定 mode 参数就完成了配置,不存在独立的配置函数。

6. 进阶玩法:从 GPIO 到舵机控制

你注意到热搜词里有"树莓派 pico 控制舵机",控制舵机用的是 PWM 功能,恰好是对 GPIO 概念的延伸。这里展开说说。

舵机的控制原理是:以 50Hz(20ms 周期)的频率发送 PWM 信号,脉宽 0.5ms~2.5ms 对应舵机角度 0°~180°。Pico 的任何一个 GPIO 引脚在 MicroPython 里都能配置成 PWM 输出,不需要额外硬件。

from machine import Pin, PWM import time # 将 GP15 初始化为 PWM servo = PWM(Pin(15)) servo.freq(50) # 50Hz 对应 20ms 周期 # 计算占空比 # 脉宽 1ms -> 占空比 = 1ms / 20ms = 5% # MicroPython PWM 的 duty_u16 范围是 0~65535 duty_1ms = int(65535 * 0.05) # 脉宽 1ms duty_1_5ms = int(65535 * 0.075) # 脉宽 1.5ms,舵机中位 duty_2ms = int(65535 * 0.1) # 脉宽 2ms # 从 0° 到 180° servo.duty_u16(duty_1ms) time.sleep(1) servo.duty_u16(duty_1_5ms) time.sleep(1) servo.duty_u16(duty_2ms) time.sleep(1) # 停止输出 servo.deinit()

注意这里的duty_u16()方法接收的值是 0~65535 的占空比级别,不是直接用毫秒数。换算公式是:

duty = 脉宽(ms) / 周期(ms) × 65535

这个坑我踩过:一开始我按直觉把duty_u16(1500)当成 1.5ms 用,结果舵机直接转到奇怪的角度。后来才反应过来,MicroPython 的 PWM 占空比用的是一整个 16 位寄存器的值,不是微秒。

7. 引脚冲突的全景排查:一次外设无法工作的完整链路排错

最后分享一次真实的排错经历。当时做一个环境监控项目,I2C 接的 OLED 屏幕死活不显示数据,但代码逻辑检查多次没有任何问题。排查过程如下,大家可以看看排查思路:

第一步:检查接线。SDA 接 GP4(物理引脚 6),SCL 接 GP5(物理引脚 7),都核对无误。VCC 和 GND 分别为 3.3V 和 GND。

第二步:硬件检测。用万用表量 SDA 和 SCL 的电平,发现两个引脚都是 0V。正常应该是 3.3V 高电平(I2C 空闲时靠上拉电阻拉高)。怀疑是总线被拉死了。

第三步:软件检查。查阅 I2C 初始化代码:

i2c = I2C(0, scl=Pin(5), sda=Pin(4), freq=400000)

看着没问题,但再用i2c.scan()扫描设备地址时,返回了空列表。

第四步:排查硬件故障。拔掉 OLED,单测 SDA 和 SCL 电平,发现仍然是 0V。问题不在 OLED,而在 Pico 本身。

第五步:回溯引脚复用。检查自己的代码,发现之前初始化过一个 Button 对象,刚好用了物理引脚 5(GPIO 4)做输入。虽然代码逻辑上没有冲突,但在 MicroPython 中,同一个物理引脚如果被前面代码占用了,后面的 I2C 初始化不会报错,但引脚电平已经被前面的配置改变了。释放引脚需要调用Pin.deinit()或重启。

第六步:重启板子并调整初始化顺序。让 I2C 初始化放在按键之前,问题解决。

这个案例暴露了一个容易被忽视的问题:MicroPython 不支持重复初始化同一个引脚。同一个物理引脚在代码中被创建了多次 Pin 对象,每次初始化的配置参数可能不同,后面的初始化可能无效或者覆盖前一个配置。严格来说,一个引脚最好只初始化一次。

另外,I2C 的 SDA/SCL 引脚需要接上拉电阻(约 4.7kΩ),这是 I2C 协议的硬件要求。Pico 板载了部分引脚的 I2C 上拉电阻,但不是所有引脚组合都有。如果你用的是非板载默认的 I2C 引脚组合,记得在外部加上拉电阻。

根据我个人经验,做 GPIO 相关项目前,先画一张引脚分配表,把每个 GPIO 分配给哪个外设、用到了什么复用功能写清楚。看似多花了五分钟,实际能省下后面几小时的排错时间。Pico 的引脚资源虽然丰富,但一旦牵扯到复用功能,冲突排查就很痛。希望这篇能帮你把 Pico 的 GPIO 玩得顺手。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/6 1:44:03

ESP32蓝牙开发:从协议原理到底层配置实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/6 1:43:59

AI Agent开放协议实战:构建发现、协商与支付的完整闭环

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/6 1:39:57

无需本地部署|Seedream 5.0 Pro 线上体验渠道全解析

摘要: 想用 Seedream 5.0 Pro 做高质量 AI 图像生成,却不想折腾本地部署?本文为你解析无需本地部署即可体验 Seedream 5.0 Pro 等主流 AI 模型的线上渠道,重点介绍卓特视觉无限画布这一在线 AI 创作工作台,帮助用户快速…

作者头像 李华
网站建设 2026/9/6 1:38:53

逻辑电平测试器设计与调试实战:从比较器选型到阈值计算

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/6 1:38:38

2026 团队素材管理软件怎么选?设计师团队实测对比

素材丢了、版本乱了、找不着了?这是很多设计师和内容团队的日常困扰。随着AIGC工具普及,团队积累的数字资产越来越多,如何高效管理图片、视频、设计源文件已成为刚性需求。本文实测对比5款主流素材管理产品,涵盖卓特视觉Dockcool、…

作者头像 李华