GPIOD 使用
GPIOD 简介
自 Linux 4.8 起,GPIO sysfs 接口已被弃用。用户空间应改用 libgpiod 来与 GPIO 字符设备进行交互。
libgpiod 是 Linux GPIO 字符设备(/dev/gpiochipX)的 C 库和工具集,提供了现代化的 GPIO 操作接口。
主要特点
- 简单易用:libgpiod 提供了简洁的 API,使得控制和操作 GPIO 设备变得简单易懂。开发者只需了解基本的 GPIO 概念和函数接口即可使用。
- 独立性:libgpiod 是一个独立的用户空间库,不依赖于任何特定的硬件平台或芯片。它适用于多种支持 GPIO 控制的嵌入式平台,如 Radxa ROCK 系列、树莓派、BeagleBone 等。
- 支持多种编程语言:libgpiod 原生支持 C 语言,同时也提供了 Python 绑定(python3-libgpiod)和其他语言的封装,使得在不同的编程语言下都可以方便地使用。
- 高效的事件监听:libgpiod 提供了用于异步事件监听的功能,例如等待 GPIO 状态变化等。这使得开发者可以实现高效的事件驱动应用程序。
- GPIO 规格支持:libgpiod 提供了对不同 GPIO 规格和编号方式的支持,包括基于 GPIO 编号和基于物理引脚编号两种方式。
安装 libgpiod
安装命令行工具
sudo apt update
sudo apt install gpiod -y
安装开发库(用于 C 编程)
sudo apt install libgpiod-dev -y
安装 Python 绑定
sudo apt install python3-libgpiod -y
验证安装
# 查看版本(Quectel Pi H1 使用 2.2.1)
apt list --installed | grep gpiod
# 查看可用的 GPIO 芯片
gpiodetect
注意:Quectel Pi H1 使用 libgpiod 2.2.1,语法与 1.x 版本不兼容。
命令行工具
libgpiod 提供了命令行工具,用于查看和控制 GPIO 设备。
前提条件:确保已安装 gpiod 工具包(
sudo apt install gpiod -y)
gpiodetect
列出系统中所有 GPIO 控制器:
gpiodetect
输出示例:
gpiochip0 [gpio0] (32 lines)
gpiochip1 [gpio1] (32 lines)
gpiochip2 [gpio2] (32 lines)
gpiochip3 [gpio3] (32 lines)
gpiochip4 [gpio4] (128 lines)
提示:Quectel Pi H1 主要使用
gpiochip4。
gpioinfo
显示 GPIO 设备信息:
# 查看所有 GPIO 芯片的信息
gpioinfo
# 查看特定芯片的信息(使用 grep 过滤)
# 注意:Quectel Pi H1 的 gpiochip4 有 176 条线路,根据需要调整数字
gpioinfo | grep -A 180 "gpiochip4"
libgpiod 版本差异:
- 1.x 版本:支持
gpioinfo /dev/gpiochip4语法- 2.x 版本:只支持
gpioinfo查看所有,需配合grep过滤特定芯片
输出示例(Quectel Pi H1 实际输出):
gpiochip4 - 176 lines:
line 0: unnamed input
line 1: unnamed input
line 2: unnamed output active-low consumer=perst
...
line 36: unnamed output
line 37: unnamed input
...
line 77: unnamed input
...
line 91: unnamed input active-low consumer=cd
...
字段说明:
unnamed:引脚未命名(Quectel Pi H1 的默认状态)input/output:引脚方向consumer=xxx:引脚被某个功能占用(如consumer=perst、consumer=cd)active-low:低电平有效
注意:
- Quectel Pi H1 的 GPIO 引脚默认为
unnamed(未命名)- 带
consumer=标记的引脚正在被其他功能使用,无法直接作为 GPIO 使用- gpiochip4 有 176 条线路
gpiofind(已移除)
重要提示:
gpiofind命令在 libgpiod 2.x 版本中已被移除。
Quectel Pi H1 使用 libgpiod 2.x,所有 GPIO 引脚默认为 unnamed(未命名),需要直接使用芯片名和引脚编号进行操作。
查看引脚信息:
# 查看特定引脚的详细信息
gpioinfo | grep "line 77"
# 查看某个范围的引脚
gpioinfo | grep -E "line (77|78|79)"
gpioget
读取 GPIO 输入:
# 读取 gpiochip4 的第 77 号引脚(必须使用 -c 选项指定芯片)
gpioget -c gpiochip4 77
# 也可以使用芯片编号
gpioget -c 4 77
# 或使用完整路径
gpioget -c /dev/gpiochip4 77
输出示例(libgpiod 2.x):
"77"=inactive
inactive表示低电平(0)active表示高电平(1)
如果需要数字格式输出:
# 使用 --numeric 选项输出 0/1
gpioget -c gpiochip4 --numeric 77
gpioset
设置 GPIO 输出:
重要提示(libgpiod 2.x):
- 默认情况下,
gpioset会持续保持设置的电平,直到程序被终止(Ctrl+C)- 程序退出后,GPIO 状态由硬件决定,不保证保持
- 必须使用
-c选项指定芯片
基本用法(持续保持状态):
# 设置 GPIO77 为高电平(持续保持,按 Ctrl+C 停止)
gpioset -c gpiochip4 77=1
# 设置为低电平
gpioset -c gpiochip4 77=0
# 也可以使用 active/inactive
gpioset -c gpiochip4 77=active
gpioset -c gpiochip4 77=inactive
# 或使用 on/off
gpioset -c gpiochip4 77=on
gpioset -c gpiochip4 77=off
设置多个引脚:
# 同时设置多个引脚
gpioset -c gpiochip4 16=1 17=0
设置后延迟退出:
# 设置高电平并保持 5 秒后退出
gpioset -c gpiochip4 -p 5s 77=1
# 保持 100 毫秒后退出
gpioset -c gpiochip4 -p 100ms 77=1
后台运行(守护进程模式):
# 设置后在后台运行
gpioset -c gpiochip4 -z 77=1
gpiomon
监控 GPIO 事件:
# 基本用法:监控 GPIO77 的状态变化(默认监控双边沿)
gpiomon -c gpiochip4 77
# 指定监控的边沿类型
gpiomon -c gpiochip4 -e rising 77 # 只监控上升沿
gpiomon -c gpiochip4 -e falling 77 # 只监控下降沿
gpiomon -c gpiochip4 -e both 77 # 监控双边沿(默认)
# 显示横幅信息
gpiomon -c gpiochip4 --banner 77
# 限制事件数量(监控 10 个事件后退出)
gpiomon -c gpiochip4 -n 10 77
# 设置空闲超时(5 秒内无事件则退出)
gpiomon -c gpiochip4 --idle-timeout 5s 77
# 添加防抖(10ms 防抖周期)
gpiomon -c gpiochip4 -p 10ms 77
使用示例:
- 运行
gpiomon -c gpiochip4 77 - 用杜邦线将 Pin7 (GPIO77) 连接到 GND 或 3.3V
- 观察终端输出的事件信息
- 按 Ctrl+C 停止监控
输出示例(libgpiod 2.x):
event: RISING EDGE offset: 77 timestamp: [ 1234.567890123]
event: FALLING EDGE offset: 77 timestamp: [ 1234.678901234]
自定义输出格式:
# 使用格式化输出
gpiomon -c gpiochip4 --format "Line %o: %E edge at %S" 77
# 输出示例:
# Line 77: rising edge at 1234.567890123
# Line 77: falling edge at 1234.678901234
GPIO 引脚映射
Quectel Pi H1 主要使用 /dev/gpiochip4 进行 GPIO 控制。
40Pin 常用引脚映射
| 物理引脚 | 引脚名称 | GPIO 编号 | GPIO 芯片 | libgpiod 使用 | 默认功能 |
|---|---|---|---|---|---|
| Pin3 | NFC_I2C_SDA | GPIO36 | gpiochip4 | gpiochip4 36 |
I2C09_SDA |
| Pin5 | NFC_I2C_SCL | GPIO37 | gpiochip4 | gpiochip4 37 |
I2C09_SCL |
| Pin7 | CAM2_RST | GPIO77 | gpiochip4 | gpiochip4 77 |
GPIO |
| Pin11 | GPIO_16 | GPIO16 | gpiochip4 | gpiochip4 16 |
GPIO/SPI/UART/I2C |
| Pin13 | GPIO_17 | GPIO17 | gpiochip4 | gpiochip4 17 |
GPIO/SPI/UART/I2C |
注意:Pin3 和 Pin5 默认配置为 I2C9 接口,如需作为 GPIO 使用,请确保没有其他设备占用。
完整的引脚映射请参考:40Pin 功能测试
查看引脚状态
使用 gpioinfo 查看引脚的当前状态:
# 查看 gpiochip4 的所有引脚(使用 grep 过滤)
gpioinfo | grep -A 180 "gpiochip4"
# 查看特定引脚(例如 GPIO77)
gpioinfo | grep "line 77"
# 查看所有已占用的引脚
gpioinfo | grep "consumer="
常见问题
命令未找到
问题:bash: gpiodetect: command not found
原因:
libgpiod 工具包未安装
解决方法:
# 安装 gpiod 工具包
sudo apt update
sudo apt install gpiod -y
# 验证安装
gpiodetect
注意:libgpiod 2.x 版本中没有
gpiofind命令,这是正常的。
权限问题
问题:Permission denied
error: unable to request line 77: Permission denied
解决方法:
使用 sudo 运行命令:
sudo gpioget -c gpiochip4 77
sudo gpioset -c gpiochip4 77=1
引脚占用问题
问题:Device or resource busy
error: unable to request line 36: Device or resource busy
原因:
- 引脚被其他进程占用(如 I2C、SPI 等)
- 引脚已被系统功能使用
解决方法:
- 检查引脚状态:
gpioinfo | grep "line 36"
- 如果引脚被占用,输出会显示
consumer=占用者信息:
line 36: unnamed output consumer=i2c-9
- 选择未被占用的引脚(输出中显示为
unused)
引脚编号错误
问题:cannot find line
gpioget: cannot find line '200'
原因:
引脚编号超出范围或引脚不存在
解决方法:
确认 Quectel Pi H1 的引脚范围:
- gpiochip4:0-175(共 176 条线路)
- 使用
gpioinfo查看:gpioinfo | grep -A 180 "gpiochip4"
libgpiod 版本问题
问题:不同版本的 API 和命令行工具差异
libgpiod 在不同版本中有显著变化。Quectel Pi H1 使用的是 libgpiod 2.2.1。
检查版本:
apt list --installed | grep gpiod
# 或
gpiodetect --version
主要版本差异:
| 功能 | libgpiod 1.x | libgpiod 2.x (Quectel Pi H1) |
|---|---|---|
| 基本语法 | gpioget gpiochip4 77 |
gpioget -c gpiochip4 77 |
| 芯片指定 | 位置参数 | 必须使用 -c 选项 |
| gpioinfo | gpioinfo /dev/gpiochip4 |
gpioinfo | grep -A 180 "gpiochip4" |
| gpioset 默认行为 | 立即退出 | 持续保持(需 Ctrl+C) |
| gpioset 持久模式 | gpioset -m signal |
默认持久(无需参数) |
| 输出格式 | 0 / 1 |
"77"=inactive / "77"=active |
| gpiofind | 支持 | 已移除 |
| gpiochip4 线路数 | 128(示例) | 176(Quectel Pi H1) |
| GPIO 命名 | 可能已命名 | Quectel Pi H1 全部 unnamed |
| C API | 旧 API | 新 API(不兼容) |
| Python API | 旧 API | 新 API(不兼容) |
关键变化总结:
- ✅ 所有命令必须使用
-c <chip>选项指定芯片 - ✅
gpioset默认持续保持状态,不再立即退出 - ✅ 输出格式改为
"line"=active/inactive - ❌
gpiofind命令已移除 - ❌ 不再支持位置参数方式指定芯片
调试技巧
常用调试命令
# 1. 查看所有 GPIO 芯片
gpiodetect
# 2. 查看 gpiochip4 的所有引脚信息
gpioinfo | grep -A 180 "gpiochip4"
# 3. 查看被占用的引脚
gpioinfo | grep "consumer="
# 4. 查看特定引脚状态
gpioinfo | grep "line 77"
# 5. 读取引脚值
gpioget -c gpiochip4 77
# 6. 设置引脚值(持续保持)
gpioset -c gpiochip4 77=1
# 7. 监控引脚事件
gpiomon -c gpiochip4 77
与 sysfs 的对比
| 特性 | sysfs(已弃用) | libgpiod |
|---|---|---|
| 接口路径 | /sys/class/gpio/ |
/dev/gpiochipX |
| 导出引脚 | 需要手动 export | 自动管理 |
| 资源管理 | 手动 unexport | 自动释放 |
| 并发访问 | 容易冲突 | 更好的资源管理 |
| 性能 | 较慢(文件操作) | 更快(ioctl) |
| 事件监听 | 支持 | 更好的支持 |
| 维护状态 | 已弃用 | 活跃维护 |
建议:新项目应使用 libgpiod 而不是已弃用的 sysfs 接口。