Linux 用户态设置GPIO控制

本文详细介绍了如何在Linux系统中通过sysfs接口在用户空间配置和使用GPIO,包括导出、删除GPIO,设置GPIO方向、电平、中断触发模式。并提供了使用poll()函数监听GPIO中断的示例代码,展示了如何响应引脚电平变化。通过这些步骤,开发者可以实现对硬件设备的控制和中断处理。
摘要由CSDN通过智能技术生成

linux内核提供了一套在用户态配置GPIO的接口,在/sys/class/gpio/目录下 
这里写图片描述
可以发现其中包含有两个文件exportunexport和若干gpiochipN 类型文件夹

  • export 
    用于将指定编号的引脚导出,作为GPIO使用
  • unexport 
    用于将导出的GPIO删除掉
  • gpiochipN 
    当前芯片中包含的GPIO控制器

GPIO使用方法

  • 添加设备接口GPIO167 
    输入:echo 167 > export 
    这里写图片描述
    可以发现,目录下出现了gpio167,如果执行命令后没有反应,表示当前的GPIO已经用作其他的功能,例如作为IIC的引脚等
  • 删除设备接口GPIO167 
    输入:echo 167 > unexport 
    这里写图片描述
    可以发现当前导出的接口被删除
  • 控制设备接口GPIO167 
    输入:echo 167 > unexport 
    这里写图片描述

    • direction 
      设置输出还是输入模式 
      • 设置为输入:echo “in” > direction
      • 设置为输出:echo “out” > direction
    • value 
      输出时,控制高低电平;输入时,获取高低电平 
      • 高电平:echo 1 > value
      • 低电平:echo 0 > value
    • edge 
      控制中断触发模式,引脚被配置为中断后可以使用poll() 函数监听引脚 
      • 非中断引脚: echo “none” > edge
      • 上升沿触发:echo “rising” > edge
      • 下降沿触发:echo “falling” > edge
      • 边沿触发:echo “both” > edge

gpiochipN目录

用来管理和控制一组gpio端口的控制器

    • base 
      和N相同,表示控制器管理的最小的端口编号。
    • lable 
      诊断使用的标志(并不总是唯一的)
    • ngpio
      控制器管理的gpio端口数量(端口范围是:N ~ N+ngpio-1)

      参考:http://blog.csdn.net/mirkerson/article/details/8464290

    • 用户态使用gpio监听中断

    • 比如我想监听PA7上的电平变化(也就是边沿触发),那么应该先向“/sys/class/gpio/gpio7/direction”写入“in”,然后向“/sys/class/gpio/gpio7/edge”写入“both”,然后对”/sys/class/gpio/gpio7/value”执行select/poll操作。

      代码如下:

      poll_test.c

      #include <stdio.h>
      #include <fcntl.h>
      #include <poll.h>
      #include <unistd.h>
      
      int main()
      {
          int fd=open("/sys/class/gpio/gpio7/value",O_RDONLY);
          if(fd<0)
          {
              perror("open '/sys/class/gpio/gpio7/value' failed!\n");  
              return -1;
          }
          struct pollfd fds[1];
          fds[0].fd=fd;
          fds[0].events=POLLPRI;
          while(1)
          {
              if(poll(fds,1,0)==-1)
              {
                  perror("poll failed!\n");
                  return -1;
              }
              if(fds[0].revents&POLLPRI)
              {
                  if(lseek(fd,0,SEEK_SET)==-1)
                  {
                      perror("lseek failed!\n");
                      return -1;
                  }
                  char buffer[16];
                  int len;
                  if((len=read(fd,buffer,sizeof(buffer)))==-1)
                  {
                      perror("read failed!\n");
                      return -1;
                  }
                  buffer[len]=0;
                  printf("%s",buffer);
              }
          }
          return 0;
      }
      

      这个小程序的作用就是就是不断poll(“/sys/class/gpio/gpio7/value”)。一旦poll()返回,就输出PA7的值。

      假设代码放在~目录下,然后输入如下命令:

      cd ~
      gcc poll_test.c -o poll_test
      echo in > /sys/class/gpio/gpio7/direction
      echo both > /sys/class/gpio/gpio7/edge
      ./poll_test
      

      用1K电阻把PA7上拉到VCC,然后用一根导线把PA7与GND连接又断开,会发现不断输出1和0(当PA7连上GND的瞬间输出0,与GND断开的瞬间输出1)。说明poll()确实能检测到电平变化。

    • Linux应用]通过sysfs在用户空间使用GPIO中断

       
      • 通过使用sysfs,Linux GPIO可以支持在用户空间进行GPIO的控制或获取状态。这样可以使用简单的工具,比如“echo”来设置输出GPIO的电平或使用“cat”来读取输入GPIO的当前值。

        1、配置内核中sysfs下的GPIO支持

               要想在用户空间访问GPIO,需要在sysfs中使能GPIO支持。

        Symbol: GPIO_SYSFS [=n]

          Type  : boolean

          Prompt: /sys/class/gpio/... (sysfs interface)

          Defined at drivers/gpio/Kconfig:51

          Depends on: GPIOLIB [=y] && SYSFS [=y] && EXPERIMENTAL [=y]

          Location:

           -> Device Drivers

             -> GPIO Support (GPIOLIB [=y])

        2、在用户空间是能GPIO

               即将GPIO导出到用户空间之中。

        ------------------------------------

        GPIO = 22

        cd = /sys/class/gpio

        ls

        echo $GPIO > export

        ls

        ------------------------------------

               注意:开始ls时,gpio22并不存在,第二个ls时,gpio22才存在。

               设置为输入并获取当前值:

        ------------------------------------

        cd /sys/class/gpio/gpio$GPIO

        echo "in" > direction

        cat value

        ------------------------------------

               设置为输出并设置值:

        ------------------------------------

        cd /sys/class/gpio/gpio$GPIO

        echo "out" > direction

        echo 1 > value 或 echo 0 > value

        ------------------------------------

        3、用作中断

               先将GPIO配置为输入,然后使用poll()来阻塞程序直到GPIO的输入电平发生改变,关键是使用POLLPRI而不是POLLIN来侦听事件;或者使用select()。

        4、查看GPIO配置

               配置内核来使能debugfs

         Symbol: DEBUG_FS [=y]

          Type  : boolean

          Prompt: Debug Filesystem

            Defined at lib/Kconfig.debug:77

            Location:

            -> Kernel hacking

               启动目标硬件并挂载debugfs

        mount -t debugfs none /sys/kernel/debug

               查看引脚配置

        cat /sys/kernel/debug/gpio

        poll示例:

        memset((void *)xfds, 0, sizeof(xfds));

        xfds[0].fd = fd;

        xfds[0].events = POLLPRI;

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

        if(ret <= 0)

        ERREXIT("poll value");

        if(xfds[0].revents & POLLPRI)

        {

        /* get value */

        ret = lseek(fd, 0, SEEK_SET);

        if(ret < 0)

        ERREXIT("lseek value");

        ret = read(fd, buf, 2);

        buf[1] = '\0';

        printf("read ret = %d, value = %s\n", ret, buf);

        if(ret != 2)

        ERREXIT("read value");

        }

        select示例:

        FD_ZERO(&exceptfds);

        FD_SET(fd, &exceptfds);

        ret = select(fd+1,NULL,NULL,&exceptfds,NULL);

        if(ret < 0)

        ERREXIT("select value");

        //else if(ret > 0)

        if(ret > 0)

        {

        /* get value */

        ret = lseek(fd, 0, SEEK_SET);

        if(ret < 0)

        ERREXIT("lseek value");

        ret = read(fd, buf, 2);

        buf[1] = '\0';

        printf("read ret = %d, value = %x\n", ret, buf[0]);

        if(ret != 2)

        ERREXIT("read value");

        }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值