功能描述

  • 操控开发板GPIO,实现GPIO输入、输出、中断

实践要点

基础知识

  • GPIO属于较简单的设备,由led编程实践可知,GPIO的操作,通常使用sysfs方式。

  • GPIO存放的目录:/sys/class/gpio

  • gpiochipX

    • 当前SoC所包含的GPIO控制器,不同芯片的GPIO控制器不同,可以去芯片的datasheet查询。I.MX6U有5个GPIO控制器,GPIO1~GPIO5,分为对应gpiochip0~gpiochip128。每一个gpiochipX文件夹用来管理一组GPIO。
    • base:该控制器所管理的这组GPIO中引脚最小的编号。
    • label:GPOIO对应的标签(名字)。
    • ngpio:该控制器所管理的GPIO引脚的数量(引脚编号范围:base ~ base + ngpio - 1)。
  • /sys/class/gpio目录下:

    • export:用于将指定编号的gpio导出。
    echo 0 > export

    上述命令表示导出gpio0。

    注意:并不是所有gpio引脚都可以成功导出。如果已经被内核占用了,则无法导出,会报Device or resource busy的错误信息。

    • unexport:取消导出指定编号的gpio。
    echo 0 > unexport
    • gpiox:导出的对应的gpio引脚对应的文件夹,用于管理、控制该GPIO引脚。
  • gpioX

    • direction:配置gpio引脚的输入或输出模式。
    echo "in" > direction
    echo "out" > direction
    • value:输出模式下,写入0/1改变gpio的状态;输入模式下,读取gpio的值。

    • active_low:用于gpio的极性控制,默认为0(gpio电平1代表高,0代表低,否则gpio电平1代表低,0代表高)。

    • edge:控制中断的触发模式。

    非中断引脚:echo "none" > edge
    上升沿触发:echo "rising" > edge
    下降沿触发:echo "falling" > edge
    边沿触发:echo "both" > edge

输入/输出

  • 这没什么好说的,导出对应的gpio后,通过sysfs方式打开对应文件,通过读写来管理或控制gpio状态即可。

中断

  • 当引脚被配置为中断后,可以使用poll()函数监听引脚的电平状态变化(poll函数可以监视一个或多个文件描述符上的I/O状态变化)。函数poll用法可查阅《Unix环境高级编程(第3版)》第408页。

  • 核心代码解析

    struct pollfd pfd;
    
    pfd.fd = open(gpioValuePath, O_RDONLY);
    if(pfd.fd == -1) {
      perror("open error");
      exit(-1);
    }
    pfd.events = POLLPRI;                     //POLLPRI 可以不阻塞地读高优先级数据,中断是一种高优先级事件
    ret = read(pfd.fd, &val, 1);              //先读取一次清除状态
    if(ret < 0) {
      perror("read error");
      close(fd);
      exit(-1);
    }   
    /*
    poll函数:
    int poll(struct pollfd fdarray[], nfds_t nfds, int timeout);
    timeout == -1 : 永远等待。当所指定的描述符中的一个已经准备好,或捕捉到一个信号时返回。 
    (0:不等待 >0:等待timeout ms)
    */
    for(;;) {
      ret = poll(&pfd, 1, -1);
      if(ret < 0) {
          perror("poll error");
          exit(-1);
      }
      else if(ret == 0) {
          printf("poll timeout.\n");
          continue;
      }
    
      if(pfd.events & POLLPRI) {            //判断中断是否触发
          //这里面可以实现自己的中断触发后执行的逻辑代码。
          if(lseek(pfd.fd, 0, SEEK_SET) < 0) {//回到文件开头
              perror("lseekk error");
              exit(-1);
          }
          if(read(pfd.fd, &val, 1) < 0) {       //读gpio value值
              perror("read error");
              exit(-1);
          }
    
          printf("GPIO中断触发,value=%c\n", val);
      }
    }

附录

代码地址:https://gitee.com/sigmapoet/zdyz-application/tree/master/02-gpio

说点什么
请文明发言!
支持Markdown语法
好耶,沙发还空着ヾ(≧▽≦*)o
Loading...