推荐使用 libgpiod 替代已弃用的 wiringpi:安装 libgpiod-dev,通过 /dev/gpiochip0 操作 gpio,需加入 gpio 用户组并调用 gpiod_line_request_output 等接口,注意 bcm 编号与 line index 区分。

用 wiringPi 库直接控制 GPIO,但别再装它了
树莓派官方已弃用 wiringPi,2024 年起新系统(如 Raspberry Pi OS Bookworm)默认不预装,且其 gpio 命令在非 root 下会报 Permission denied 或 Unable to determine hardware version。现在更稳妥的方式是走 Linux 标准的 sysfs 接口(/sys/class/gpio)或更现代的 libgpiod。
推荐用 libgpiod:它支持 edge-triggered 中断、批量操作、无需 root(靠 udev 规则),且和内核主线同步更新。
- 安装:
sudo apt install libgpiod-dev,头文件在<gpiod.h></gpiod.h> - 编译时加
-lgpiod,例如:g++ -o blink blink.cpp -lgpiod - 设备路径固定为
/dev/gpiochip0(树莓派通常只有一个 chip),别硬编码芯片编号
gpiod_chip_open() 失败常见原因
调用 gpiod_chip_open("/dev/gpiochip0") 返回 nullptr,大概率不是代码写错,而是权限或设备节点问题。
- 检查设备是否存在:
ls /dev/gpiochip*—— 若无输出,说明内核没启用 GPIO 字符设备驱动(CONFIG_GPIO_CDEV=y) - 普通用户需加入
gpio用户组:sudo usermod -aG gpio $USER,然后重新登录 - 某些旧镜像默认禁用 cdev,需在
/boot/config.txt加一行:dtoverlay=gpio-noirq(仅调试用)或换用标准 overlay - 别用
sudo绕过权限——这掩盖真实问题,且中断回调在 root 下无法触发用户空间信号
设置输出引脚并翻转电平的最小可靠写法
用 libgpiod 控制一个 LED 引脚(比如 BCM 18),关键不是“怎么亮”,而是“怎么避免时序错乱或资源泄漏”。
立即学习“C++免费学习笔记(深入)”;
#include <gpiod.h>
#include <unistd.h>
int main() {
struct gpiod_chip *chip = gpiod_chip_open("/dev/gpiochip0");
struct gpiod_line *line = gpiod_chip_get_line(chip, 18); // BCM 编号,非物理针脚号
gpiod_line_request_output(line, "blink", GPIOD_LINE_ACTIVE_STATE_HIGH);
for (int i = 0; i < 5; ++i) {
gpiod_line_set_value(line, 1);
usleep(500000);
gpiod_line_set_value(line, 0);
usleep(500000);
}
gpiod_line_release(line);
gpiod_chip_close(chip);
}
- 必须调用
gpiod_line_request_output(),否则set_value会静默失败 -
GPIOD_LINE_ACTIVE_STATE_HIGH表示逻辑高 = 物理高电平;若接的是共阴 LED,这个值就对;若接继电器模块(常低有效),得用GPIOD_LINE_ACTIVE_STATE_LOW - 别用
sleep()——精度差,用usleep()或nanosleep() - 务必调用
gpiod_line_release(),否则下次运行可能报Device or resource busy
读取按钮输入时为什么总读到抖动值
硬件消抖没做,纯靠软件延时判断,会导致多次触发或漏触发。libgpiod 本身不处理抖动,得自己加策略。
- 优先用内核级 debounce:查
gpiod_line_is_used()是否被占用,然后尝试gpiod_line_set_config()配置debounce_period_us(需内核 ≥ 5.5 且驱动支持) - 简单应用可用“两次采样”法:读到变化后,等待 20ms 再读一次,两次一致才确认有效
- 避免轮询:改用
gpiod_line_request_input_flags()+gpiod_line_event_wait()等待边沿事件,省 CPU 且响应及时 - 注意:树莓派 GPIO 没内置上拉/下拉的软件配置能力,必须外接电阻或用
gpio命令初始化(如raspi-gpio set 18 pu),libgpiod 不提供该功能
最易被忽略的一点:BCM 编号和物理针脚号混用。树莓派文档里标的是物理针脚(如 Pin 12 = BCM 18),但 libgpiod 的 line index 是按芯片内部顺序排的,不是 BCM 号——得用 gpiod_chip_get_line_by_name() 或查 gpioinfo 输出确认实际映射。










