3. 网关外设GPIO控制
任务目标
在工业IoT网关上,通过Linux用户空间控制GPIO引脚,实现两个功能:驱动LED以1Hz频率闪烁,以及检测按键按下并打印事件。本案例采用libgpiod库(新版内核推荐方式),适用于Debian/Ubuntu嵌入式系统。
环境与依赖
- 硬件:任意GPIO扩展芯片(如PCA9555)或CPU原生GPIO,本例以
gpiochip0为例 - 系统:Linux内核≥4.8,已加载
gpio_ich/gpio_pca953x等驱动 - 安装libgpiod开发库:
sudo apt install libgpiod-dev gpiod - 接线:LED正极接GPIO17(经330Ω电阻),按键一端接GPIO27、另一端接GND(按下为低电平)
关键完整代码
// gpio_demo.c - 使用libgpiod控制LED闪烁与按键检测
#include <gpiod.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
static int running = 1;
void stop_handler(int sig) { running = 0; }
int main(void) {
struct gpiod_chip *chip;
struct gpiod_line *led_line, *btn_line;
int ret, val;
// 打开GPIO芯片(默认chip0,可按实际修改)
chip = gpiod_chip_open_by_name("gpiochip0");
if (!chip) { perror("打开gpiochip0失败"); return 1; }
// 获取LED引脚(GPIO17)并配置为输出
led_line = gpiod_chip_get_line(chip, 17);
if (!led_line) { perror("获取LED引脚失败"); goto err_chip; }
ret = gpiod_line_request_output(led_line, "led_demo", 0);
if (ret < 0) { perror("配置LED为输出失败"); goto err_led; }
// 获取按键引脚(GPIO27)并配置为输入(启用内部上拉)
btn_line = gpiod_chip_get_line(chip, 27);
if (!btn_line) { perror("获取按键引脚失败"); goto err_led; }
ret = gpiod_line_request_input_flags(btn_line, "btn_demo",
GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP);
if (ret < 0) { perror("配置按键为输入失败"); goto err_btn; }
// 注册Ctrl+C退出
signal(SIGINT, stop_handler);
printf("GPIO演示开始:LED闪烁,按下按键打印事件(Ctrl+C退出)\n");
while (running) {
// LED翻转
val = gpiod_line_get_value(led_line);
gpiod_line_set_value(led_line, !val);
// 非阻塞读取按键(低电平有效)
val = gpiod_line_get_value(btn_line);
if (val == 0) {
printf("[%ldms] 按键按下\n", (long)(clock() * 1000 / CLOCKS_PER_SEC));
// 简单消抖:等待100ms后确认
usleep(100000);
if (gpiod_line_get_value(btn_line) == 0) {
printf("按键事件确认\n");
while (gpiod_line_get_value(btn_line) == 0)
usleep(10000); // 等待释放
}
}
usleep(500000); // 500ms延时,实现1Hz闪烁
}
printf("\n退出,清理资源\n");
gpiod_line_release(btn_line);
err_btn:
gpiod_line_release(led_line);
err_led:
gpiod_chip_close(chip);
err_chip:
return 0;
}
编译与运行
# 编译(需安装libgpiod-dev)
gcc -o gpio_demo gpio_demo.c -lgpiod
# 运行(需要root权限访问GPIO)
sudo ./gpio_demo
验证方法与判定标准
- LED闪烁验证:观察LED以约1Hz频率(每秒亮灭各一次)闪烁。若LED不亮,检查GPIO编号是否正确(可用
gpioinfo gpiochip0查看可用引脚)及接线极性。 - 按键检测验证:按下按键,终端应输出
按键按下和按键事件确认;松开后再次按下可重复触发。若按键无响应,确认按键接在GPIO27与GND之间,且内部上拉已启用(按下为低电平)。 - 资源释放验证:按Ctrl+C退出时,程序应正常打印退出信息并释放GPIO资源,无错误提示。
常见问题
- GPIO编号不匹配:不同网关的GPIO编号映射不同,先用
gpiodetect和gpioinfo确认芯片名称与引脚号。 - 权限不足:访问GPIO需要root权限,若提示
Permission denied,使用sudo运行或添加udev规则。 - 按键抖动:本代码已做简单消抖(100ms确认),若仍误触发可适当延长消抖时间。