搭建一个和linux开发者知识共享和学习的平台
分类: 嵌入式
2024-07-08 10:19:01
每个 gpio 控制器(gpiochip)在 /dev 中都会有一个字符设备,可以使用文件操作(open、read、write、ioctl、poll、close)来管理 gpio 行并与之交互,输入 ls /dev/gpiochip*,可以看到 gpio 的所有字符设备:
尽管这个新的字符设备接口可以防止使用 echo 和 cat 等标准命令行操作 gpio,但与 sysfs 接口相比,它有一些优点:
gpio 的分配与正在使用它的进程相关联,从而改进了对用户空间进程使用哪些 gpio 线路的控制;
一次读取或写入多条 gpio 线路;
可以按名称找到 gpio 控制器和 gpio 线路;
可以配置引脚的状态(开源、开漏等);
捕获事件(来自 gpio 线路的中断)的轮询过程是可靠的。
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