在嵌入式设备中对GPIO的操作是最基本的操作。一般的做法是写一个单独驱动程序,网上大多数的例子都是这样的。其实linux下面有一个通用的GPIO操作接口,那就是我要介绍的 “/sys/class/gpio” 方式。

首先,看看系统中有没有“/sys/class/gpio”这个文件夹。如果没有请在编译内核的时候加入   Device Drivers  —>  GPIO Support  —>     /sys/class/gpio/… (sysfs interface)。

/sys/class/gpio 的使用说明:

01 gpio_operation 通过/sys/文件接口操作IO端口 GPIO到文件系统的映射

02 * 控制GPIO的目录位于/sys/class/gpio

03 * /sys/class/gpio/export文件用于通知系统需要导出控制的GPIO引脚编号

04 * /sys/class/gpio/unexport 用于通知系统取消导出

05 * /sys/class/gpio/gpiochipX目录保存系统中GPIO寄存器的信息,包括每个寄存器控制引脚的起始编号        base,寄存器名称,引脚总数 导出一个引脚的操作步骤

06 * 首先计算此引脚编号,引脚编号 = 控制引脚的寄存器基数 + 控制引脚寄存器位数

07 * 向/sys/class/gpio/export写入此编号,比如12号引脚,在shell中可以通过以下命令实现,

echo 12 > /sys/class/gpio/export

命令成功后生成/sys/class/gpio/gpio12目录,如果没有出现相应的目录,说明此引脚不可导出:

08

09 * direction文件,定义输入输入方向,可以通过下面命令定义为输出

10   echo out > /sys/class/gpio/gpio12/direction

11 * direction接受的参数:in, out, high, low。high/low同时设置方向为输出,

并将value设置为相应的1/0。

12 * value文件是端口的数值,为1或0.

13   echo 1 >/sys/class/gpio/gpio12/value

编写控制程序

GPIO的配置文件在/sys/class/gpio目录下,控制程序可以分为四个步骤:

  • 配置GPIO:在/sys/class/gpio目录下可以看到文件export,调用该文件以实现配置。该文件对所有GPIO编号,从0开始。GPIOn_x的编号为32*n+x,例如此处用的GPIO1_6的编号为32*1+6=38。在终端输入:# echo "38" > /sys/class/gpio/export,在此回到目录/sys/class/gpio下,可以看到产生了一个新的目录./gpio38,里面包含了该IO口的输入输出设置等配置文件。注意:export文件只有root写权限,执行上述命令或者以后用C编写的可执行文件要以ROOT身份执行。
  • 设置GPIO的方向(输入输出):在终端输入:# echo "out" > /sys/class/gpio/gpio38/direction,即设置该GPIO为输出。
  • 设置GPIO的输出电平:在终端输入:#echo "1" > /sys/class/gpio/gpio38/value,即设置GPIO输出高电平,输入echo "0" > /sys/class/gpio/gpio38/value设置GPIO输出低电平。
  • 关闭GPIO:在终端输入:#echo "38" > /sys/class/gpio/unexport,即删除GPIO配置文件,可以看到目录gpio38已经被删除。

    下面是C语言编写的GPIO控制例程,实现LED的每隔一秒闪烁一次。

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    int main(void)
    {
    FILE *p=NULL;
    int i=0;
    p = fopen("/sys/class/gpio/export","w");
    fprintf(p,"%d",38);
    fclose(p);
    p = fopen("/sys/class/gpio/gpio38/direction","w");
    fprintf(p,"out");
    fclose(p);
    for(i=0;i<100;i++)
    {
    p = fopen("/sys/class/gpio/gpio38/value","w");
    fprintf(p,"%d",1);
    sleep(1);
    fclose(p);
    p = fopen("/sys/class/gpio/gpio38/value","w");
    fprintf(p,"%d",0);
    sleep(1);
    fclose(p);
    }
    p = fopen("/sys/class/gpio/unexport","w");
    fprintf(p,"%d",38);
    fclose(p);
    return 0;
    }

     
     
    下面实现按键输入的读取操作
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>

    int main(void)
    {
    FILE *p=NULL;
    char i[100]={0,};

    p = fopen("/sys/class/gpio/export","w");
    fprintf(p,"%d",161);
    fclose(p);
    p = fopen("/sys/class/gpio/gpio161/direction","w");
    fprintf(p,"in");  //配置成输入
    fclose(p);

    while(1)
    {
    //以只读方式打开
    p = fopen("/sys/class/gpio/gpio161/value","r");
    //使文件读写定位到0位置
    fseek(p , 0 , 0);
    #if 0
    //将文件内容输出到存储器i中,注意要以字符串的方式,否则会出错
    fscanf(p,"%s",i);
    #else
    //从文件中读出数据到存储器i中
    fread(i , 1, 1 ,p);
    #endif
    //以字符的方式将读到的值打印出
    printf("key = %c \r\n",i[0]);
    sleep(1);
    //注意这里必须要关闭,然后再次读时再重新打开,这样只面的内容才会更新
    fclose(p);
    }
    return 0;
    }

     
    /*********************************************************************************/
    查看当前系统下已使用的GPIO:
    # cat /sys/kernel/debug/gpio
     

    用户态使用gpio监听中断

    首先需要将该gpio配置为中断

    echo  "rising" > /sys/class/gpio/gpio12/edge

    以下是伪代码

    int gpio_id;

    struct pollfd fds[1];

    gpio_fd = open("/sys/class/gpio/gpio12/value",O_RDONLY);

    if( gpio_fd == -1 )

    err_print("gpio open");

    fds[0].fd = gpio_fd;

    fds[0].events  = POLLPRI;

    ret = read(gpio_fd,buff,10);

    if( ret == -1 )

    err_print("read");

    while(1){

    ret = poll(fds,1,-1);

    if( ret == -1 )

    err_print("poll");

    if( fds[0].revents & POLLPRI){

    ret = lseek(gpio_fd,0,SEEK_SET);

    if( ret == -1 )

    err_print("lseek");

    ret = read(gpio_fd,buff,10);

    if( ret == -1 )

    err_print("read");

    /*此时表示已经监听到中断触发了,该干事了*/

    ...............

    }

    }

    记住使用poll()函数,设置事件监听类型为POLLPRI和POLLERR在poll()返回后,使用lseek()移动到文件开头读取新的值或者关闭它再重新打开读取新值。必须这样做否则poll函数会总是返回。

linux下对/sys/class/gpio中的gpio的控制 (转)的更多相关文章

  1. 在linux下,查看一个运行中的程序, 占用了多少内存

    1. 在linux下,查看一个运行中的程序, 占用了多少内存, 一般的命令有 (1). ps aux: 其中  VSZ(或VSS)列 表示,程序占用了多少虚拟内存. RSS列 表示, 程序占用了多少物 ...

  2. Linux下用文件IO的方式操作GPIO(/sys/class/gpio)(转)

    通过sysfs方式控制GPIO,先访问/sys/class/gpio目录,向export文件写入GPIO编号,使得该GPIO的操作接口从内核空间暴露到用户空间,GPIO的操作接口包括direction ...

  3. Linux下用文件IO的方式操作GPIO(/sys/class/gpio)

    通过sysfs方式控制GPIO,先访问/sys/class/gpio目录,向export文件写入GPIO编号,使得该GPIO的操作接口从内核空间暴露到用户空间,GPIO的操作接口包括direction ...

  4. linux下开发,解决cocos2d-x中编译出现的一个小问题, undefined reference to symbol &#39;pthread_create@@GLIBC_2.2.5&#39;

    解决cocos2d-x中编译出现的一个小问题 对于cocos2d-x 2.×中编译中,若头文件里引入了#include "cocos-ext.h",在进行C++编译的时候会遇到例如 ...

  5. linux下使用vim替换文件中的^M换行符

    在linux下打开windows编辑过的文本,会出现由于换行符不一致而导致的内容格式错乱的问题.最常见的就是出现^M . 我出现的问题是:在windows编辑过的文件,传到linux上后再用vim打开 ...

  6. [转] Linux下用文件IO的方式操作GPIO(/sys/class/gpio)

    点击阅读原文 一.概述 通过 sysfs 方式控制 GPIO,先访问 /sys/class/gpio 目录,向 export 文件写入 GPIO 编号,使得该 GPIO 的操作接口从内核空间暴露到用户 ...

  7. nginx详解(代理服务器的解释+nginx 在linux 下的安装+nginx.conf 中的配置解释)

    一.概论 1.什么是代理服务器 代理服务器,客户机在发送请求时,不会直接发送给目的主机,而是先发送给代理服务器,代理服务接受客户机请求之后,再向主机发出,并接收目的主机返回的数据,存放在代理服务器的硬 ...

  8. Linux下的vi编辑命令中查找·替换详解

    一.查找 查找命令 /pattern<Enter> :向下查找pattern匹配字符串 ?pattern<Enter>:向上查找pattern匹配字符串 使用了查找命令之后,使 ...

  9. 解决linux下oracle进入sqlplus环境中后退键显示^H、上下键无效与ctrl+l无法清屏等问题【weber出品必属精品】

    习惯linux中上下键回退历史输入的人们肯定也希望sqlplus中也能实现相同的效果,可是不幸的是,sqlplus中不提供诸多方便的快捷键,这个时候我们就需要另外安装一个插件来实现这个想法. 这个插件 ...

随机推荐

  1. CSU 1216异或最大值 (0-1 trie树)

    Description 给定一些数,求这些数中两个数的异或值最大的那个值 Input 多组数据.第一行为数字个数n,1 <= n <= 10 ^ 5.接下来n行每行一个32位有符号非负整数 ...

  2. Spring Cloud 入门 Consul-Client服务提供

    前面介绍了 Rureka Client服务提供, 只需要改pom.xml部分内容 1.pom.xml <?xml version="1.0" encoding="U ...

  3. keepalived实现nginx的高可用

    1.使用yum安装keepalived yum install keepalived -y 2.修改配置文件keepalived.conf 主服务器配置文件 global_defs { router_ ...

  4. 6-1 md5加密

    1.导入hashlib模块,使用它的md5方法进行加密 import hashlib # import md5 python2 s = 'admin123' # .将字符串类型转换成byte类型才能加 ...

  5. js常用的2中排序方法:冒泡排序和快速排序

    冒泡排序:例如9 4 5 6 8 3 2 7 10 1 首先:9和4比较  4放前   4 9 5 6 8 3 2 7 10 1 4和5比较   4不动   4 9 5 6 8 3 2 7 10 1 ...

  6. python 函数 闭包 (节省内存空间 html 获取网页的源码)

    #闭包:嵌套函数,内部函数调用外部函数的变量 # def outer(): # a = 1 # def inner(): # print(a) # inner() # outer() def oute ...

  7. wlr快捷键

    ref:http://www.cnblogs.com/zhangyang/archive/2011/07/22/2113856.html   Windows Live Writer提供了许多方便的快捷 ...

  8. android gesture检测

    1.关于on<TouchEvent>的返回值 a return value of true from the individual on<TouchEvent> methods ...

  9. 《Cracking the Coding Interview》——第7章:数学和概率论——题目2

    2014-03-20 01:59 题目:有n只蚂蚁在正n边形的n个顶点,同时以同速率开始沿着边走.每只蚂蚁走的方向是随机的,那么这些蚂蚁至少有两只发生碰撞的概率是多少. 解法:只有所有蚂蚁都往一个方向 ...

  10. USACO Section1.2 Dual Palindromes 解题报告

    dualpal解题报告 —— icedream61 博客园(转载请注明出处)-------------------------------------------------------------- ...