Chinaunix首页 | 论坛 | 博客
  • 博客访问: 323587
  • 博文数量: 101
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 774
  • 用 户 组: 普通用户
  • 注册时间: 2018-10-15 14:13
个人简介

搭建一个和linux开发者知识共享和学习的平台

文章分类

全部博文(101)

文章存档

2024年(15)

2023年(24)

2022年(27)

2019年(8)

2018年(27)

分类: 嵌入式

2024-07-08 10:19:01

GPIO(General Purpose Input/Output,通用输入/输出接口),是微控制器或微处理器上的引脚,可以被编程为输入或输出,用于与外部设备进行通信。在 Linux 系统中,通过内核提供的用户空间接口,开发者能够轻松地读取、设置 GPIO 的状态,实现对外部设备的控制和监测。

在 Linux 系统内部,Linux 内核通过生产者/消费者模型实现对 GPIO 的访问。有生产 GPIO 线路的驱动程序(GPIO控制器驱动程序)和消耗 GPIO 线路的驱动程序(键盘、触摸屏、传感器等)。
为了管理 GPIO 注册和分配,Linux 内核中有一个名为 gpiolib 的框架。该框架为在内核空间和用户空间应用程序中运行的设备驱动程序提供了一个 API。


旧版本方式:sysfs 接口

在 Linux kernel 4.7 版本之前,管理用户空间中 GPIO 线路的接口一直通过在 /sys/class/gpio 导出的文件在 sysfs 中。因此,如果想要将某个 GPIO 设置成输出,且让这个 GPIO 输入高电平,整体步骤如下:
    
确定GPIO线路的编号;
    
将 GPIO 编号写入到 /sys/class/gpio/export;
    
将 GPIO 线路配置为输出,对应设置的文件为 /sys/class/gpio/gpioX/direction;
    
将 1 写入到 /sys/class/gpio/gpioX/value,使 GPIO 输出高电平。
    
新版本方式:chardev 接口

从 Linux kernel 4.8 版本开始,GPIO sysfs 接口被弃用,现在有一个基于字符设备的新 API,可以从用户空间访问 GPIO 线路。

每个 GPIO 控制器(gpiochip)在 /dev 中都会有一个字符设备,可以使用文件操作(open、read、write、ioctl、poll、close)来管理 GPIO 行并与之交互,输入 ls /dev/gpiochip*,可以看到 GPIO 的所有字符设备:

尽管这个新的字符设备接口可以防止使用 echo 和 cat 等标准命令行操作 GPIO,但与 sysfs 接口相比,它有一些优点:

    GPIO 的分配与正在使用它的进程相关联,从而改进了对用户空间进程使用哪些 GPIO 线路的控制;

    
一次读取或写入多条 GPIO 线路;
    
可以按名称找到 GPIO 控制器和 GPIO 线路;
    
可以配置引脚的状态(开源、开漏等);
    
捕获事件(来自 GPIO 线路的中断)的轮询过程是可靠的。
 

  1. gpiod 库及其命令行

使用 chardev 接口,可以安装libgpiod 项目

1https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/ 

来使用,这是个与 Linux GPIO 字符设备交互的 C 库和工具。

gpiod 库的命令行

安装好库和工具后,可以使用一些命令来确认是否安装成功。例如,检查可用的 GPIO 芯片:

1gpiodetect

查看 GPIO 芯片的信息命令(以 gpiochip0 为例):

1gpioinfo /dev/gpiochip0 

这个命令显示的信息很多,line 是GPIO 线的编号(从 0 到 287),后面是 GPIO 线的名称,未命名的线显示为 unnamed,unused表示该 GPIO 线目前未被使用,input 表示该 GPIO 线配置为输入模式,output 表示该 GPIO 线配置为输出模式,active-high 表示该 GPIO 线的活动电平为高电平。


用 gpioset 命令可以设置 GPIO 线路,假设现在要改变 75 号 GPIO 的输出状态(输出为 1),具体命令如下:

1gpioset 0 75=1 

命令中的 0 表示 gpiochip0,75 为 GPIO 线路号,1 为写入值。

执行后,GPIO 75 的输出值立刻变为 1,相较于 sysfs 接口的调用,方便了非常多。


gpioget 命令将读取 GPIO 线路的值。例如,读取 GPIO 65 的值,命令如下:

1gpioget 0 65

所有这些命令的源代码都可以在 libgpiod 仓库中找到。

gpiod 库函数的应用

gpiod 库提供了很多 API,可以直接对 GPIO 线路进行操作:

1struct gpiod_chip *gpiod_chip_open(const char *path); 2struct gpiod_line *gpiod_chip_get_line(struct gpiod_chip *chip, unsigned int offset); 3int gpiod_line_request_input(struct gpiod_line *line, const char *consumer); 4int gpiod_line_get_value(struct gpiod_line *line);

总结来说,这几个函数的主要作用是打开 GPIO 芯片、获取 GPIO 线路、将 GPIO 线路配置为输入模式并读取其电平值。通过这些步骤,可以实现对 GPIO 线状态的监测和响应。

以下 C 程序使用 libgpiod 读取 GPIO 70 的例子:

 // gpio_line.c  
2 
3#include   
4#include   
5#include   
6#include   
7  
8int main()  
9{ 
10    struct gpiod_chip *chip; 
11    struct gpiod_line *line; 
12    int req, value; 
13 
14    chip = gpiod_chip_open("/dev/gpiochip0"); 
15    if (!chip) { 
16        perror("Failed to open GPIO chip"); 
17        return -1; 
18    } 
19 
20    line = gpiod_chip_get_line(chip, 70); 
21    if (!line) { 
22        gpiod_chip_close(chip); 
23        perror("Failed to get line"); 
24        return -1; 
25    } 
26 
27    req = gpiod_line_request_input(line, "gpio_state"); 
28    if (req) { 
29        gpiod_chip_close(chip); 
30        fprintf(stderr"Failed to request line as input: %s\n", strerror(errno)); 
31        return -1; 
32    } 
33 
34    value = gpiod_line_get_value(line); 
35    if (value < 0) { 
36        gpiod_chip_close(chip); 
37        fprintf(stderr"Failed to get line value: %s\n", strerror(errno)); 
38        return -1; 
39    } 
40 
41    printf("GPIO value is: %d\n", value); 
42 
43    gpiod_chip_close(chip); 
44    return 0; 
45}

编译和运行命令如下:

1gcc -o gpio_line gpio_line.c -lgpiod 2./gpio_line
阅读(19668) | 评论(0) | 转发(0) |
2

上一篇:YUV图像格式详解

下一篇:MIPI CSI驱动移植

给主人留下些什么吧!~~