Heng30的博客
搜索 分类 关于 订阅

Linux用户空间控制GPIO

2025-03-20

从用户空间访问GPIO也是比较常用的功能。下面的例子就演示了如何在Linux用户空间访问GPIO,并控制其引脚电平。

实验环境

raspberry pi3b

Linux raspberrypi 6.1.21-v8+ #1642 SMP PREEMPT Mon Apr  3 17:24:16 BST 2023 aarch64 GNU/Linux

测试代码

// simple.c

#include <assert.h>
#include <fcntl.h>
#include <linux/gpio.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    struct gpiohandle_request led, button;
    struct gpiohandle_data data;
    int status = 0;

    int fd = open("/dev/gpiochip0", O_RDWR);
    assert(fd >= 0);

    // 设置GPIO 16为输出
    led.flags = GPIOHANDLE_REQUEST_OUTPUT;
    strcpy(led.consumer_label, "LED");
    memset(led.default_values, 0, sizeof(led.default_values));
    led.lines = 1;  // 设置引脚个数
    led.lineoffsets[0] = 16;
    assert(ioctl(fd, GPIO_GET_LINEINFO_IOCTL, &led) >= 0);

    // 设置GPIO 17为输入
    button.flags = GPIOHANDLE_REQUEST_INPUT;
    strcpy(button.consumer_label, "BUTTON");
    memset(button.default_values, 0, sizeof(button.default_values));
    button.lines = 1;   // 设置引脚个数
    button.lineoffsets[0] = 17;
    assert(ioctl(fd, GPIO_GET_LINEINFO_IOCTL, &button) >= 0);

    printf("Led fd: %d, Button fd: %d\n", led.fd, button.fd);

    // 设置Led GPIO输出高电平
    data.values[0] = 1;
    if(ioctl(led.fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data) < 0) {
        perror("ioctl Led error");
        status = -1;
        goto end;
    }

    // 获取Button GPIO电平
    if(ioctl(button.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data) < 0) {
        perror("ioctl Button error");
        status = -1;
        goto end;
    }

    printf("Buttion is %s\n", (data.values[0] > 0) ? "pressed" : "not pressed");

    sleep(2);

end:
    close(fd);
    close(led.fd);
    close(button.fd);
    return status;
}

编译脚本

#!/bin/sh

all: simple.c
        gcc -g -o simple simple.c

clean:
        -rm simple