在嵌入式设备中对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. CMD批处理复制目录下所有文件

    从我接触编程时,WIN7已经是最普及的系统了. 有一天,我需要在服务器更新某个软件或游戏的时候,我都需要先在其中一台服务器下载更新, 然后同步到其他服务器,而且这种操作也是非常频繁的,我就想写个批处理 ...

  2. 【ACM之行】◇第一站◇ 2018HDU多校赛总结

    ◇第一站◇ 2018HDU多校赛 十场多校赛下来,也算是给一个初中生开了眼界……看着清华一次次AK(默默立下flag),看着自己被同校的高中生完虐,一个蒟蒻只能给dalao们垫脚

  3. (转)为什么国外 MMORPG 中不采用自动寻路等功能?

    不只是自动寻路,现在网游中的教学引导系统,辅助系统的功能强大程度,友好程度都可以说到了变态的程度,开发这些功能投入的资源甚至要超过游戏内容本身.究其原因,还是竞争越来越激烈,人心越来越浮躁,游戏商家为 ...

  4. No module named 'PyQt5.sip'

    使用pyinstaller打包python文件为windows可执行程序可能遇到的问题 pyinstaller yourprogram.py打包的程序双击打开一闪而过,提示上面标题的错误 把pycom ...

  5. POJ:1995-Raising Modulo Numbers(快速幂)

    Raising Modulo Numbers Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 9512 Accepted: 578 ...

  6. STM32遇到的问题

    1.GPIO输出实验的时候,原来的库和现成的源代码有出入?导致实验现象不同,delay_ms,主要集中在这个函数上面 2.按键输入的时候,LED和KEY 初始化全部放在主函数,有按下按键以后,灯闪烁不 ...

  7. ansible-2

    软件相关模块 rpm 和yum 的区别: rpm: redhat package manager :yum可以解决依赖关系 yum 源配置: cat /etc/yum.repos.d/epel.rep ...

  8. Java语言基础---转义符

    转义符 转义符使用“\”表示.常用转义符如下: 1.‘\n’回车 2.‘\t’制表位字符,一个表示向右跳8-10个字符 3.‘\\’表示’\’ 4.‘\’’表示单引号 5.‘\’’’表示双引号 6.‘ ...

  9. Web安全1&沙箱隔离

    1.web安全 Web安全的本质是信任问题 •由于信任,正常处理用户恶意的输入导致问题的产生 •非预期的输入(就是不是程序员预期的客户的输入) 安全是木桶原理,短的那块板决定的木桶世纪能装多少水,同样 ...

  10. 常用数据库连接URL地址大全

    1.Oracle8/8i/9i数据库(thin模式) Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); ...