zoukankan      html  css  js  c++  java
  • linux 应用层使用gpio

    • 使用这个代码之前 首先确认开发版的 “/sys/class/” 目录下有gpio这个文件夹,如果没有就需要配置linux内核
    • /**
       * @author emlsyx
       * @email yangx_1118@163.com
       * @create date 2020-02-19 19:11:53
       * @modify date 2020-02-19 19:11:53
       * @desc [description]
       */
      #include <stdlib.h>
      #include <stdio.h>
      #include <string.h>
      #include <unistd.h>
      #include <fcntl.h>
      #include <linux/poll.h>
      
      #define err_out(fmt, ...)                                                      
          do                                                                         
          {                                                                          
              printf(fmt, ##__VA_ARGS__);                                            
              printf("<%s>  "%s()" %d error
      ", __FILE__, __FUNCTION__, __LINE__); 
          } while (0)
      
      #define open_gpio_file(path, flag, fd)              
          do                                              
          {                                               
              fd = open(path, flag);                      
              if (fd < 0)                                 
              {                                           
                  err_out(""%s" open failed 
      ", path); 
                  return (-1);                            
              }                                           
          } while (0);
      
      /**
       * @brief : gpio 导出
       * @param : pin
       * @retval: 0 成功; -1失败
       */
      static int gpio_export(const int pin)
      {
          int fd, len;
          char buffer[64];
          char path[64];
      
          sprintf(&path[0], "/sys/class/gpio/gpio%d", pin);
          /* 文件不存在时,导出gpio*/
          if (access(path, F_OK) != 0)
          {
              memset(path, 0, 64);
              sprintf(&path[0], "/sys/class/gpio/export");
              open_gpio_file(path, O_WRONLY, fd);
              len = snprintf(buffer, sizeof(buffer), "%d", pin);
      
              if (write(fd, buffer, len) < 0)
              {
                  err_out("write failed to export gpio!
      ");
                  return -1;
              }
              close(fd);
          }
          return 0;
      }
      /**
       * @brief : gpio 卸载
       * @param : pin
       * @retval: 0 成功; -1失败
       */
      static int gpio_unexport(const int pin)
      {
          int fd, len;
          char buffer[64];
          char path[64];
      
          sprintf(&path[0], "/sys/class/gpio/gpio%d", pin);
          /* 文件存在时,卸载gpio*/
          if (access(path, F_OK) == 0)
          {
              memset(path, 0, 64);
              sprintf(&path[0], "/sys/class/gpio/unexport");
              open_gpio_file(path, O_WRONLY, fd);
              len = snprintf(buffer, sizeof(buffer), "%d", pin);
              if (write(fd, buffer, len) < 0)
              {
                  err_out("write failed to unexport gpio!
      ");
                  return -1;
              }
              close(fd);
          }
          return 0;
      }
      
      /**
       * @brief : gpio 方向控制
       * @param : dir 方向(in/out)
       * @retval: 0 成功; -1失败
       */
      static int gpio_direction(const int pin, const char *dir)
      {
          int fd;
          char path[64];
          int w_len = ((dir[0] == 'i') && (dir[1] == 'n')) ? 2 : 3;
      
          snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/direction", pin);
          open_gpio_file(path, O_WRONLY, fd);
          if (write(fd, dir, w_len) < 0)
          {
              err_out("Failed to set direction!
      ");
              return -1;
          }
      
          close(fd);
          return 0;
      }
      
      /**
       * @brief : gpio 写
       * @param : 0 / 1
       * @retval: 0 成功; -1失败
       */
      static int gpio_write(const int pin, const int value)
      {
          int fd;
          char path[64];
          const char *val[] = {"0", "1"};
      
          snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", pin);
          open_gpio_file(path, O_WRONLY, fd);
      
          if (write(fd, val[value], 1) < 0)
          {
              err_out("Failed to write value!
      ");
              return -1;
          }
      
          close(fd);
          return 0;
      }
      
      /**
       * @brief : gpio 读
       * @param : 读取的引脚值
       * @retval: 返回引脚的值 0 / 1
       */
      static int gpio_read(const int pin)
      {
          int fd;
          char path[64];
          char value_str[3];
      
          snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", pin);
          open_gpio_file(path, O_RDONLY, fd);
          if (read(fd, value_str, 3) < 0)
          {
              err_out("Failed to read value!
      ");
              return -1;
          }
      
          close(fd);
          return (atoi(value_str));
      }
      
      /**
       * @brief : gpio 中断控制
       * @param : 0 none 表示引脚为输入,不是中断引脚
       *   @arg : 1 rising 表示引脚为中断输入,上升沿触发
       *   @arg : 2 falling 表示引脚为中断输入,下降沿触发
       *   @arg : 3 both 表示引脚为中断输入,边沿触发
       * @retval:
       */
      static int gpio_edge(const int pin, int edge)
      {
          int fd;
          char path[64];
          const char *dir_str[] = {"none", "rising", "falling", "both"};
      
          if (edge > 3)
          {
              err_out("Failed edge parameter error
      ");
              return -1;
          }
      
          snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/edge", pin);
          open_gpio_file(path, O_WRONLY, fd);
      
          if (write(fd, dir_str[edge], strlen(dir_str[edge])) < 0)
          {
              err_out("Failed to set edge!
      ");
              return -1;
          }
      
          close(fd);
          return 0;
      }
      
      int main()
      {
          char buff[10], res;
          int led_fd, key_fd;
          struct pollfd fds;
      
          /* 按键led指示灯*/
          gpio_export(55);
          gpio_direction(55, "out");
          gpio_write(55, 0);
      
          /* 按键引脚初始化*/
          gpio_export(70);
          gpio_direction(70, "in");
          gpio_edge(70, 2);
          open_gpio_file("/sys/class/gpio/gpio70/value", O_RDONLY, key_fd);
      
          /* poll 操作的文件符号*/
          fds.fd = key_fd;
      
          /* 经测试io中断产生后,正常会发送POLLPRI 这个中断,循环中必须等待这个事件*/
          fds.events = POLLPRI | POLLERR;
      
          /* 真实发生的事件*/
          fds.revents = 0;
          while (1)
          {
              int ret = poll(&fds, 1, -1);
              if (!ret)
              {
                  err_out("poll time out
      ");
              }
              else
              {
                  if (fds.revents & POLLPRI)
                  {
                      gpio_write(55, gpio_read(55) ? 0 : 1);
      
                      res = lseek(fds.fd, 0, SEEK_SET); /* 读取按键值*/
                      if (res == -1)
                      {
                          printf("lseek failed!
      ");
                          return -1;
                      }
                      res = read(fds.fd, buff, sizeof(buff));
                      if (res == -1)
                      {
                          perror("read failed!
      ");
                          return -1;
                      }
                      printf("fds.revents %d key value %s 
      ", fds.revents, buff);
                  }
              }
          }
      
          return 0;
      }
  • 相关阅读:
    《追风筝的人》书摘与笔记
    《清单革命》读书笔记
    华为HMS Core音频服务,让有声世界更动听
    Unity平台 | 快速集成华为性能管理服务
    【Demo见真章】投稿赢HarmonyOS手机Beta公测名额
    【开发者必看】2020年移动应用趋势洞察白皮书
    华为帐号服务升级,助力应用快速验证用户身份
    简单的路径规划案例分享
    Cocos|快速集成华为AGC云存储服务
    Flutter平台 | 零代码快速集成AGC崩溃服务
  • 原文地址:https://www.cnblogs.com/emlsyx/p/12332857.html
Copyright © 2011-2022 走看看