1. 点亮第一个LED

点亮第一个LED 学习卡片

任务目标

在嵌入式Linux环境下,通过操作GPIO子系统控制一个LED的亮灭。本案例使用sysfs接口(适用于Linux 4.8以下内核)或libgpiod(适用于新内核),实现LED的点亮与熄灭,并验证GPIO控制的基础流程。

环境与依赖

  • 硬件:任意带GPIO的嵌入式平台(如Raspberry Pi、i.MX6ULL、全志H3等),LED串联限流电阻(约330Ω)接至GPIO与GND之间
  • 内核:Linux 4.8+(推荐使用libgpiod),或旧内核使用sysfs
  • 软件依赖:libgpiod-dev(新内核)、gcc交叉编译工具链

核心实现

以下代码使用libgpiod库,通过GPIO chip和line操作实现LED控制。该实现适用于现代Linux内核(4.8+),是当前GPIO控制的标准方式。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <gpiod.h>

#define LED_CHIP "/dev/gpiochip0"
#define LED_LINE 17  /* GPIO17,根据实际硬件调整 */

int main(int argc, char *argv[])
{
    struct gpiod_chip *chip;
    struct gpiod_line *line;
    int ret;
    int i;

    /* 打开GPIO chip */
    chip = gpiod_chip_open(LED_CHIP);
    if (!chip) {
        perror("gpiod_chip_open");
        return -1;
    }

    /* 获取LED对应的line */
    line = gpiod_chip_get_line(chip, LED_LINE);
    if (!line) {
        perror("gpiod_chip_get_line");
        gpiod_chip_close(chip);
        return -1;
    }

    /* 请求line为输出模式,初始低电平 */
    ret = gpiod_line_request_output(line, "led_demo", 0);
    if (ret < 0) {
        perror("gpiod_line_request_output");
        gpiod_chip_close(chip);
        return -1;
    }

    /* 闪烁5次:亮1秒,灭1秒 */
    for (i = 0; i < 5; i++) {
        gpiod_line_set_value(line, 1);  /* 点亮LED */
        printf("LED ON\n");
        sleep(1);

        gpiod_line_set_value(line, 0);  /* 熄灭LED */
        printf("LED OFF\n");
        sleep(1);
    }

    /* 释放资源 */
    gpiod_line_release(line);
    gpiod_chip_close(chip);
    printf("Demo finished.\n");
    return 0;
}

编译与运行

# 交叉编译(以arm-linux-gnueabihf为例)
arm-linux-gnueabihf-gcc -o led_demo led_demo.c -lgpiod

# 将led_demo拷贝至目标板后执行
./led_demo

验证方法

  • 观察LED是否以1秒间隔闪烁5次,同时串口/终端输出"LED ON"/"LED OFF"交替信息
  • 若LED不亮,使用gpioinfo /dev/gpiochip0确认GPIO17是否被其他驱动占用,或检查硬件连接(LED正极接GPIO,负极经电阻接GND)
  • 若使用旧内核(无libgpiod),可改用sysfs方式:echo 17 > /sys/class/gpio/export,然后设置方向和value

常见问题

  • GPIO编号不匹配:不同平台的GPIO编号映射不同,需查阅芯片手册或使用gpioinfo确认实际编号
  • 权限不足:运行程序时需root权限或加入gpio用户组
  • GPIO被占用:检查设备树中是否已将该引脚配置为其他功能