16 GPIO 应用编程

目录

1 应用层如何操控 GPIO

2 GPIO 应用编程之输出

3 GPIO 应用编程之输入

4 GPIO 应用编程之中断

本文参考正点原子教程,作为学习笔记使用。

应用层如何操控 GPIO

        GPIO也是通过 sysfs 方式进行操控,进入到/sys/class/gpio 目录下,

        可以看到该目录下包含两个文件 export unexport 以及 5 gpiochipX X 等于 0 32 64 96 128 )命名的文件夹。
 gpiochipX:当前 SoC 所包含的 GPIO 控制器 ,我们知道 I.MX6UL/I.MX6ULL 一共包含了 5 GPIO 控制器,分别为 GPIO1 GPIO2 GPIO3 GPIO4 GPIO5 ,在这里分别对应 gpiochip0 gpiochip32 、 gpiochip64、 gpiochip96 gpiochip128 5 个文件夹,每一个 gpiochipX 文件夹用来管理一组 GPIO 。随便进入到其中某个目录下,可以看到这些目录下包含了如下文件:
        在这个目录我们主要关注的是 base label ngpio 这三个属性文件,这三个属性文件均是只读、不可写。
        base:与 gpiochipX 中的 X 相同,表示 该控制器所管理的这组 GPIO 引脚中最小的编号每一个 GPIO引脚都会有一个对应的编号,Linux 下通过这个编号来操控对应的 GPIO 引脚。
        label:该组 GPIO 对应的标签,也就是名字
        ngpio:该控制器所管理的 GPIO 引脚的数量(所以引脚编号范围是: base ~ base+ngpio-1 )。
        对于给定的一个 GPIO 引脚,如何计算它在 sysfs 中对应的编号呢?其实非常简单,譬如给定一个 GPIO引脚为 GPIO4_IO16,那它对应的编号是多少呢?首先我们要确定 GPIO4 对应于 gpiochip96,该组 GPIO 引 脚的最小编号是 96 (对应于 GPIO4_IO0 ),所以 GPIO4_IO16 对应的编号自然是 96 + 16 = 112 ;同理 GPIO3_IO20 对应的编号是 64 + 20 = 84
export 用于将指定编号的 GPIO 引脚导出。在使用 GPIO 引脚之前,需要将其导出,导出成功之后才能使用它。注意 export 文件是只写文件,不能读取,将一个指定的编号写入到 export 文件中即可将对应的 GPIO 引脚导出,譬如:
echo 0 > export # 导出编号为 0 的 GPIO 引脚(对于 I.MX6UL/I.MX6ULL 来说,也就是GPIO1_IO0)
        导出成功之后会发现在/sys/class/gpio 目录下生成了一个名为 gpio0 的文件夹( gpioX X 表示对应的编号),如下图 所示。这个文件夹就是导出来的 GPIO 引脚对应的文件夹,用于管理、控制该 GPIO 引脚,稍后再给大家介绍。
unexport 将导出的 GPIO 引脚删除。当使用完 GPIO 引脚之后,我们需要将导出的引脚删除,同样该文件也是只写文件、不可读,譬如:
echo 0 > unexport # 删除导出的编号为 0 的 GPIO 引脚
        删除成功之后,之前生成的 gpio0 文件夹就会消失!
        以上就给大家介绍了/sys/class/gpio 目录下的所有文件和文件夹,控制 GPIO 引脚主要是通过 export 导出之后所生成的 gpioX X 表示对应的编号)文件夹,在该文件夹目录下存在一些属性文件可用于控制 GPIO引脚的输入、输出以及输出的电平状态等。
        Tips:需要注意的是,并不是所有 GPIO 引脚都可以成功导出,如果对应的 GPIO 已经在内核中被使用了,那便无法成功导出,打印如下信息:
        那也就是意味着该引脚已经被内核使用了,譬如某个驱动使用了该引脚,那么将无法导出成功!
gpioX
        将指定的编号写入到 export 文件中,可以导出指定编号的 GPIO 引脚,导出成功之后会在 /sys/class/gpio 目录下生成对应的 gpioX X 表示 GPIO 的编号)文件夹,以前面所生成的 gpio0 为例,进入到 gpio0 目录, 该目录下的文件如下所示:
        我们主要关心的文件是 active_low direction edge 以及 value 这四个属性文件,接下来分别介绍这四个属性文件的作用:
        direction: 配置 GPIO 引脚为输入或输出模式。该文件可读、可写,读表示查看 GPIO 当前是输入还是输出模式,写表示将 GPIO 配置为输入或输出模式;读取或写入操作可取的值为 "out" (输出模式)和"in" (输入模式),如下所示:
        value: GPIO 配置为输出模式下,向 value 文件写入 "0" 控制 GPIO 引脚输出低电平,写入 "1" 则控制 GPIO 引脚输出高电平。在输入模式下,读取 value 文件获取 GPIO 引脚当前的输入电平状态。 譬如:
# 获取 GPIO 引脚的输入电平状态
echo "in" > direction
cat value
# 控制 GPIO 引脚输出高电平
echo "out" > direction
echo "1" > value
        active_low: 这个属性文件用于控制极性,可读可写,默认情况下为 0 ,譬如:
# active_low 等于 0 时
echo "0" > active_low
echo "out" > direction
echo "1" > value #输出高
echo "0" > value #输出低

# active_low 等于 1 时
$ echo "1" > active_low
$ echo "out" > direction
$ echo "1" > value #输出低
$ echo "0" > value #输出高
        由此看出,active_low 的作用已经非常明显了,对于输入模式来说也同样适用。
        edge: 控制中断的触发模式,该文件可读可写。在配置 GPIO 引脚的中断触发模式之前,需将其设置为输入模式:
        非中断引脚:echo "none" > edge
        上升沿触发:echo "rising" > edge
        下降沿触发:echo "falling" > edge
        边沿触发:echo "both" > edge
        当引脚被配置为中断后可以使用 poll() 函数监听引脚的电平状态变化,在后面的示例中将向大家介绍。

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;
}

//执行程序时需要传入两个参数,argv[1]指定 GPIO 的编号、argv[2]指定输出电平状态(0 表示低电平、1 表示高电平)。
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);
 
}

GPIO 应用编程之输入

GPIO 应用编程之中断

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不做拖延王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值