除了LED类设备可以通过sysfs文件系统控制以外,还可以使用该虚拟文件系统控制GPIO的高低电平,输入以及中断检测。
进入目录sys/class/gpio下可以看到有如下文件,其中gpiochip0对应硬件的GPIO0,gpiochip1对应硬件的GPIO1,以此类推。每个gpiochipX都管理一组32个gpio管脚。

如果要使用某一个gpio管脚,需要先使用export命令将其导出。例如命令echo 0 > export,可以以将GPIO0_IO0导出,同理使用命令echo 0 > unexport命令删除GPIO0_IO0管脚

打开导出的管脚可以看到有如下文件 :

active_low:代表有效极性
direction:代表输入或输出
value:代表管脚电平
对于给定的一个 GPIO 引脚,如何计算它在 sysfs 中对应的编号?
GPIO4_IO16,GPIO4 对应于 gpiochip96,所以GPIO4_IO16对应的编号就是96 + 16 = 112.
应用程序编写:
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <string.h>
-
-
- static char gpio_path[100];
- static int gpio_config(const char *attr, const char *val)
- {
- char file_path[100];
- int len;
- int fd;
- sprintf(file_path, "%s/%s", gpio_path, attr);
- if (0 > (fd = open(file_path, O_WRONLY))) {
- perror("open error");
- return fd;
- }
-
- len = strlen(val);
- if (len != write(fd, val, len)) {
- perror("write error");
- close(fd);
- return -1;
- }
-
- close(fd); //关闭文件
- return 0;
- }
-
-
- int main(int argc, char *argv[])
- {
- /* 校验传参 */
- if (3 != argc) {
- fprintf(stderr, "usage: %s <gpio> <value>\n", argv[0]);
- exit(-1);
- }
- /* 判断指定编号的 GPIO 是否导出 */
- sprintf(gpio_path, "/sys/class/gpio/gpio%s", argv[1]);
- if (access(gpio_path, F_OK)) {//如果目录不存在 则需要导出
- int fd;
- int len;
- if (0 > (fd = open("/sys/class/gpio/export", O_WRONLY))) {
- perror("open error");
- exit(-1);
- }
- len = strlen(argv[1]);
- if (len != write(fd, argv[1], len)) {//导出 gpio
- perror("write error");
- close(fd);
- exit(-1);
- }
- close(fd); //关闭文件
- }
- /* 配置为输出模式 */
- if (gpio_config("direction", "out"))
- exit(-1);
- /* 极性设置 */
- if (gpio_config("active_low", "0"))
- exit(-1);
- /* 控制 GPIO 输出高低电平 */
- if (gpio_config("value", argv[2]))
- exit(-1);
- /* 退出程序 */
- exit(0);
- }
代码流程:代码使用样例: ./testApp 36 1,将编号为36的GPIO管脚设置为高电平
① 检查是否导出要操作的管脚,如果未导出则将其导出
② 将管脚配置为输出模式,有效极性低,输出对应的电平。
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <string.h>
-
-
- static char gpio_path[100];
- static int gpio_config(const char *attr, const char *val)
- {
- char file_path[100];
- int len;
- int fd;
- sprintf(file_path, "%s/%s", gpio_path, attr);
- if (0 > (fd = open(file_path, O_WRONLY))) {
- perror("open error");
- return fd;
- }
- len = strlen(val);
- if (len != write(fd, val, len)) {
- perror("write error");
- close(fd);
- return -1;
- }
- close(fd); //关闭文件
- return 0;
- }
-
- int main(int argc, char *argv[])
- {
- char file_path[100];
- char val;
- int fd;
- /* 校验传参 */
- if (2 != argc) {
- fprintf(stderr, "usage: %s <gpio>\n", argv[0]);
- exit(-1);
- }
- /* 判断指定编号的 GPIO 是否导出 */
- sprintf(gpio_path, "/sys/class/gpio/gpio%s", argv[1]);
- if (access(gpio_path, F_OK)) {//如果目录不存在 则需要导出
- int len;
- if (0 > (fd = open("/sys/class/gpio/export", O_WRONLY))) {
- perror("open error");
- exit(-1);
- }
- len = strlen(argv[1]);
- if (len != write(fd, argv[1], len)) {//导出 gpio
- perror("write error");
- close(fd);
- exit(-1);
- }
- close(fd); //关闭文件
- }
-
- /* 配置为输入模式 */
- if (gpio_config("direction", "in"))
- exit(-1);
- /* 极性设置 */
- if (gpio_config("active_low", "0"))
- exit(-1);
- /* 配置为非中断方式 */
- if (gpio_config("edge", "none"))
- exit(-1);
- /* 读取 GPIO 电平状态 */
- sprintf(file_path, "%s/%s", gpio_path, "value");
- if (0 > (fd = open(file_path, O_RDONLY))) {
- perror("open error");
- exit(-1);
- }
-
- if (0 > read(fd, &val, 1)) {
- perror("read error");
- close(fd);
- exit(-1);
- }
- printf("value: %c\n", val);
- /* 退出程序 */
- close(fd);
- exit(0);
- }
代码流程:代码使用样例: ./testApp 36 ,读取编号为36的管脚电平
① 检查是否导出要操作的管脚,如果未导出则将其导出
② 将管脚配置为输入模式,有效极性低,读取对应电平。