GPIO的使用
最近又要做嵌入式了,发现这块还是非常非常重要,再补一下吧。

在日常的工作中,其实要做的就是两点。1 查看GPIO的状态。2 修改GPIO的状态。
1 查看GPIO状态
命令有很多种,甚至不同的平台也有自己的命令,这里就用最通用命令gpiod来看吧。
首先还是安装:
sudo apt update
sudo apt install -y gpiod
基本查看:
tom@tom:~$ gpiodetect
gpiochip0 [pinctrl-rp1] (54 lines)
gpiochip10 [gpio-brcmstb@107d508500] (32 lines)
gpiochip11 [gpio-brcmstb@107d517c00] (17 lines)
gpiochip12 [gpio-brcmstb@107d517c20] (6 lines)
gpiochip13 [gpio-brcmstb@107d508520] (4 lines)
可以看到,这里分了5组,对应了5个GPIO控制器,也就是chip0,chip1...。一般我们用chip0就可以了,作用如下:
piochip0 [pinctrl-rp1] (54 lines) → 40 针排针全部在这里(外接 LCD、传感器、串口 IO 唯一要用的)
gpiochip10/11/12/13 [gpio-brcmstb@xxx] → 主芯片 BCM2712 内置内部 GPIO,不引出到 40 针插座,gpio-brcmstb = Broadcom STB 架构 GPIO,属于主芯片 BCM2712 本体,无物理排针引出,作用全是板载内置功能。用户一般完全不用碰。gpiochip10 32 路,主要负责:PCIe、SDIO (Wifi / 蓝牙 SD 总线)、USB 电源使能、USB 过流检测、蓝牙串口控制脚
gpiochip11 17 路,AON(始终上电不掉电)电源域 GPIO:PMIC 中断、HDMI I2C 复位、系统电源控制、2712 休眠唤醒
gpiochip12 6 路,辅助低速电源 / 状态信号
gpiochip13 4 路,SD 卡电源、卡检测、核心电源门控
具体看某一路的状态:
tom@tom:~$ gpioget --chip gpiochip0 17
"17"=inactive
查看整个chip0的状态:
tom@tom:~$ gpioinfo --chip gpiochip0
gpiochip0 - 54 lines:
line 0: "ID_SDA" input
line 1: "ID_SCL" input
line 2: "GPIO2" input
line 3: "GPIO3" input
line 4: "GPIO4" output consumer="dc"
line 5: "GPIO5" input
line 6: "GPIO6" input
line 7: "GPIO7" output active-low consumer="spi0 CS1"
line 8: "GPIO8" output active-low consumer="spi0 CS0"
line 9: "GPIO9" input
line 10: "GPIO10" input
line 11: "GPIO11" input
line 12: "GPIO12" input
line 13: "GPIO13" input
line 14: "GPIO14" input
line 15: "GPIO15" input
line 16: "GPIO16" output consumer="reset"
line 17: "GPIO17" input
line 18: "GPIO18" input
line 19: "GPIO19" input
line 20: "GPIO20" input
line 21: "GPIO21" input
line 22: "GPIO22" input
line 23: "GPIO23" input
line 24: "GPIO24" input
line 25: "GPIO25" input
line 26: "GPIO26" input
line 27: "GPIO27" input
line 28: "PCIE_RP1_WAKE" input
line 29: "FAN_TACH" input
line 30: "HOST_SDA" input
line 31: "HOST_SCL" input
line 32: "ETH_RST_N" output active-low consumer="phy-reset"
line 33: "-" input
line 34: "CD0_IO0_MICCLK" output consumer="cam0_reg"
line 35: "CD0_IO0_MICDAT0" input
line 36: "RP1_PCIE_CLKREQ_N" input
line 37: "-" input
line 38: "CD0_SDA" input
line 39: "CD0_SCL" input
line 40: "CD1_SDA" input
line 41: "CD1_SCL" input
line 42: "USB_VBUS_EN" output
line 43: "USB_OC_N" input
line 44: "RP1_STAT_LED" output active-low consumer="PWR"
line 45: "FAN_PWM" output
line 46: "CD1_IO0_MICCLK" output consumer="cam1_reg"
line 47: "2712_WAKE" input
line 48: "CD1_IO1_MICDAT1" input
line 49: "EN_MAX_USB_CUR" output
line 50: "-" input
line 51: "-" input
line 52: "-" input
line 53: "-" input
这里也就是0~27是可以控制的,可以连接到40Pin的引脚,其余的内部板载硬件专用引脚,最好不要动。
第二列的ID_SDA这个就是端口在设备树里面的名字。其余的状态解释如下:
| 状态类别 | gpiod 状态文本 / 属性 | 物理含义 | 典型应用场景 / 固件工程师视角 |
| 方向 (Direction) | input |
输入状态,高阻抗,只读电平。 | 读中断、按键、传感器状态采样。 |
output |
输出状态,主动驱动外设电平。 | 控制 LED、控制电源开关(EN)、RESET 信号。 | |
| 极性 (Polarity) | active-high |
高电平有效(默认值,通常不显式打印)。 | 标准的正逻辑控制。 |
active-low |
低电平有效。软件逻辑与物理电平反转。 | 常见于 RESET_N、CS_N 或低电平触发的 LED。 |
|
| 内部偏置 (Bias) | pull-up |
开启 SoC 内部上拉电阻(通常为几K到几十K欧姆)。 | 物理引脚悬空时,强行让其稳定在高电平,防止噪声干扰引发误中断。 |
pull-down |
开启 SoC 内部下拉电阻。 | 物理引脚悬空时,强行让其稳定在低电平(0V)。 | |
bias-disable |
关闭内部上下拉(Floating/浮空)。 | 当外部电路已经焊接了强上拉/下拉电阻时使用,避免电阻并联改变阻值。 | |
| 驱动模式 (Drive) | push-pull |
推挽输出(默认)。引脚能主动拉高,也能主动拉低。 | 绝大多数高低电平控制的标准配置,驱动能力强。 |
open-drain |
开漏输出。引脚只能主动拉低(GND),释放时呈高阻态。 | 常见于 I2C 总线(SDA/SCL)或多个设备共享一条中断线的场景(线与逻辑),需外接上拉电阻。 | |
open-source |
开源输出(极少用)。引脚只能主动拉高,释放时呈高阻态。 | 与开漏相反,需外接下拉电阻。 | |
| 占用状态 (Usage) | used / kernel |
该引脚已经被内核中的某个驱动程序(Driver)申请占用了。 | 如果你在用户态通过 gpioset 去控这个引脚,会直接报错 Device or resource busy。 |
unused |
引脚闲置。 | 用户态可以随时通过 gpiod 工具接管并控制。 |
一般来说,要隔绝某个GPIO,直接设置成Input就可以了。
树莓派自己的命令结果如下:
tom@tom:~$ pinctrl
0: ip pu | hi // ID_SDA/GPIO0 = input
1: ip pu | hi // ID_SCL/GPIO1 = input
2: a3 pu | hi // GPIO2 = SDA1
3: a3 pu | hi // GPIO3 = SCL1
4: op dh pu | hi // GPIO4 = output
5: no pu | -- // GPIO5 = none
6: no pu | -- // GPIO6 = none
7: op dh pu | hi // GPIO7 = output
8: op dh pu | hi // GPIO8 = output
9: a0 pn | lo // GPIO9 = SPI0_MISO
10: a0 pn | lo // GPIO10 = SPI0_MOSI
11: a0 pn | lo // GPIO11 = SPI0_SCLK
12: no pd | -- // GPIO12 = none
13: no pd | -- // GPIO13 = none
14: a4 pn | hi // GPIO14 = TXD0
15: a4 pu | hi // GPIO15 = RXD0
16: op dl pd | lo // GPIO16 = output
17: no pd | -- // GPIO17 = none
18: no pd | -- // GPIO18 = none
19: no pd | -- // GPIO19 = none
20: no pd | -- // GPIO20 = none
21: no pd | -- // GPIO21 = none
22: no pd | -- // GPIO22 = none
23: no pd | -- // GPIO23 = none
24: no pd | -- // GPIO24 = none
25: no pd | -- // GPIO25 = none
26: no pd | -- // GPIO26 = none
27: no pd | -- // GPIO27 = none
28: no pd | lo // PCIE_RP1_WAKE/GPIO28 = none
29: no pu | lo // FAN_TACH/GPIO29 = none
30: no pu | -- // HOST_SDA/GPIO30 = none
31: no pu | -- // HOST_SCL/GPIO31 = none
32: op dh pd | hi // ETH_RST_N/GPIO32 = output
33: no pd | lo // GPIO33 = none
34: op dl pd | lo // CD0_IO0_MICCLK/GPIO34 = output
35: no pd | lo // CD0_IO0_MICDAT0/GPIO35 = none
36: no pd | lo // RP1_PCIE_CLKREQ_N/GPIO36 = none
37: no pd | lo // GPIO37 = none
38: ip pd | hi // CD0_SDA/GPIO38 = input
39: ip pd | hi // CD0_SCL/GPIO39 = input
40: ip pd | hi // CD1_SDA/GPIO40 = input
41: ip pd | hi // CD1_SCL/GPIO41 = input
42: a2 pd | hi // USB_VBUS_EN/GPIO42 = VBUS_EN1
43: a2 pu | hi // USB_OC_N/GPIO43 = VBUS_OC1
44: op dh pd | hi // RP1_STAT_LED/GPIO44 = output
45: a0 pd | hi // FAN_PWM/GPIO45 = PWM1_CHAN3
46: op dl pd | lo // CD1_IO0_MICCLK/GPIO46 = output
47: no pd | lo // 2712_WAKE/GPIO47 = none
48: no pd | lo // CD1_IO1_MICDAT1/GPIO48 = none
49: op dl pd | lo // EN_MAX_USB_CUR/GPIO49 = output
50: no pd | -- // GPIO50 = none
51: no pd | -- // GPIO51 = none
52: no pu | -- // GPIO52 = none
53: no pu | hi // GPIO53 = none
100: ip pd | lo // GPIO0 = input
101: op dh pu | hi // 2712_BOOT_CS_N/GPIO1 = output
102: a6 pn | hi // 2712_BOOT_MISO/GPIO2 = VC_SPI0_MISO
103: a5 pn | hi // 2712_BOOT_MOSI/GPIO3 = VC_SPI0_MOSI
104: a6 pn | lo // 2712_BOOT_SCLK/GPIO4 = VC_SPI0_SCLK
105: ip pd | lo // GPIO5 = input
106: ip pd | lo // GPIO6 = input
107: ip pd | lo // GPIO7 = input
108: ip pd | lo // GPIO8 = input
109: ip pd | lo // GPIO9 = input
110: ip pd | lo // GPIO10 = input
111: ip pd | lo // GPIO11 = input
112: ip pd | lo // GPIO12 = input
113: ip pd | lo // GPIO13 = input
114: a1 pd | lo // PCIE_SDA/GPIO14 = SPI_S_MOSI_OR_BSC_S_SDA
115: a1 pd | lo // PCIE_SCL/GPIO15 = SPI_S_SCK_OR_BSC_S_SCL
116: ip pd | lo // GPIO16 = input
117: ip pd | lo // GPIO17 = input
118: ip pd | lo // GPIO18 = input
119: ip pd | lo // GPIO19 = input
120: ip pu | hi // PWR_GPIO/GPIO20 = input
121: ip pd | lo // 2712_G21_FS/GPIO21 = input
122: ip pd | lo // GPIO22 = input
123: ip pd | lo // GPIO23 = input
124: a3 pn | lo // BT_RTS/GPIO24 = UART_RTS_0
125: a4 pu | lo // BT_CTS/GPIO25 = UART_CTS_0
126: a4 pn | hi // BT_TXD/GPIO26 = UART_TXD_0
127: a4 pu | hi // BT_RXD/GPIO27 = UART_RXD_0
128: op dh pd | hi // WL_ON/GPIO28 = output
129: op dh pd | hi // BT_ON/GPIO29 = output
130: a4 pn | hi // WIFI_SDIO_CLK/GPIO30 = SD2_CLK
131: a4 pu | hi // WIFI_SDIO_CMD/GPIO31 = SD2_CMD
132: a4 pu | hi // WIFI_SDIO_D0/GPIO32 = SD2_DAT0
133: a3 pu | hi // WIFI_SDIO_D1/GPIO33 = SD2_DAT1
134: a4 pu | hi // WIFI_SDIO_D2/GPIO34 = SD2_DAT2
135: a3 pu | hi // WIFI_SDIO_D3/GPIO35 = SD2_DAT3
200: a6 pd | hi // RP1_SDA/AON_GPIO0 = VC_SDA0
201: a7 pd | hi // RP1_SCL/AON_GPIO1 = VC_SCL0
202: op dh pd | hi // RP1_RUN/AON_GPIO2 = output
203: op dl pd | lo // SD_IOVDD_SEL/AON_GPIO3 = output
204: op dh pd | hi // SD_PWR_ON/AON_GPIO4 = output
205: a6 pu | lo // SD_CDET_N/AON_GPIO5 = SD_CARD_PRES_G
206: ip pu | hi // SD_FLG_N/AON_GPIO6 = input
207: ip pd | lo // AON_GPIO7 = input
208: ip pd | lo // 2712_WAKE/AON_GPIO8 = input
209: op dh pd | hi // 2712_STAT_LED/AON_GPIO9 = output
210: ip pd | lo // AON_GPIO10 = input
211: ip pd | lo // AON_GPIO11 = input
212: ip pd | lo // PMIC_INT/AON_GPIO12 = input
213: a3 pu | lo // UART_TX_FS/AON_GPIO13 = VC_TXD0
214: a3 pu | hi // UART_RX_FS/AON_GPIO14 = VC_RXD0
215: ip pd | lo // AON_GPIO15 = input
216: ip pu | hi // AON_GPIO16 = input
232: a1 -- | hi // HDMI0_SCL/AON_SGPIO0 = HDMI_TX0_BSC_SCL
233: a1 -- | hi // HDMI0_SDA/AON_SGPIO1 = HDMI_TX0_BSC_SDA
234: a1 -- | hi // HDMI1_SCL/AON_SGPIO2 = HDMI_TX1_BSC_SCL
235: a1 -- | hi // HDMI1_SDA/AON_SGPIO3 = HDMI_TX1_BSC_SDA
236: a2 -- | hi // PMIC_SCL/AON_SGPIO4 = BSC_M2_SCL
237: a2 -- | hi // PMIC_SDA/AON_SGPIO5 = BSC_M2_SDA
可以看到的状态如下:
op输出 /ip输入 /no未分配pu上拉、pd下拉、pn浮空hi高电平、lo低电平
具体解读:
1. 复用功能字段(ip /op/a0/a3/a4 /no)
- ip = input 普通 GPIO 输入模式
- op = output 普通 GPIO 输出模式
- a0/a3/a4 = alt0/alt3/alt4 复用外设功能(SPI/I2C/UART 等)
- no = none 未分配功能,浮空闲置
2. 驱动类型(dh /dl,只输出 op 才有)
- dh:drive-high 推挽高驱动//这里大电流可以用来驱动LED,长距离传输,高速信号等。
- dl:drive-low 低驱动强度
3. 偏置 bias(pu /pd/pn)
- pu:pull-up 内部上拉
- pd:pull-down 内部下拉
- pn:pull-none 无上下拉(浮空)
4. 右侧电平(hi /lo/--)
- hi:当前物理引脚高电平
- lo:当前物理引脚低电平
- --:无有效电平(闲置 no 脚读不出稳定值)
2 设置GPIO状态
对于设置,主要是以下一个可以设置。
方向,输出的值(输出有限),上下拉偏置,中断边缘 edge(输入有限)。
1) Direction (core feature)
- Input
- Output (with initial value)
Yes, this is the most basic thing:
GPIOD_LINE_REQUEST_DIRECTION_INPUTGPIOD_LINE_REQUEST_DIRECTION_OUTPUT
2) Output value (if output mode)
- Set HIGH / LOW
- e.g.
gpiod_line_set_value()
So direction + state are separate concepts:
- direction = configuration
- value = logic level
3) Bias (pull-up / pull-down / none)
Modern gpiod supports internal resistors:
- pull-up 外部悬空时,引脚稳定读到高电平 1,外部接 GND 才会变 0。
- pull-down 外部悬空稳定读到低电平 0;外部接 VDD 才变 1。
- disabled 内部电阻断开,完全靠外部电路决定电平。此时悬空时电平飘忽不定,高低乱跳,极易误触发。
This is hardware-dependent.
4) Edge detection (interrupt behavior)
For input GPIOs:
- rising edge 0→1 跳变时触发中断
- falling edge 1→0 跳变时触发中断
- both edges 0↔1 任意跳变都触发
Used for:
- buttons
- sensors
- interrupts
老式写法如下:
# 导出gpio0
echo 0 > /sys/class/gpio/export
# 设方向输出
echo out > /sys/class/gpio/gpio0/direction
# 输出高电平
echo 1 > /sys/class/gpio/gpio0/value
# 输入配置:上拉+上升沿中断
echo in > /sys/class/gpio/gpio1/direction
echo pull-up > /sys/class/gpio/gpio1/bias
echo rising > /sys/class/gpio/gpio1/edge
现在一般也用gpiod
# gpiochip0, pin2 设输出高
gpioset gpiochip0 2=1
# 输入、上拉、双边沿监听
gpiodctl set gpiochip0 3 direction=in bias=pull-up edge=both
好了,差不多,感觉知识点都复习到了。
更多推荐

所有评论(0)