linux中通用GPIO接口的操作--文件IO方式

0 前言
    本文描述如果通过文件IO sysfs方式控制EasyARM GPIO端口。通过sysfs方式控制GPIO,先访问/sys/class/gpio目录,向export文件写入GPIO编号,使得该GPIO的操作接口从内核空间暴露到用户空间,GPIO的操作接口包括direction和value等,direction控制GPIO方向,而value可控制GPIO输出或获得GPIO输入。

          用户空间访问gpio,即通过sysfs接口访问gpio,下面是/sys/class/gpio目录下的三种文件: 

            --export/unexport文件

            --gpioN指代具体的gpio引脚

            --gpio_chipN指代gpio控制器


  (1) export/unexport文件接口:

               /sys/class/gpio/export,该接口只能写不能读

               用户程序通过写入gpio的编号来向内核申请将某个gpio的控制权导出到用户空间

               比如  echo 19 > export 

               上述操作会为19gpio创建一个节点gpio19,此时/sys/class/gpio目录下边生成一个gpio19的目录

               /sys/class/gpio/unexport和导出的效果相反。 

               比如 echo 19 > unexport

               上述操作将会移除gpio19这个节点。

 

 (2) /sys/class/gpio/gpioN

          指代某个具体的gpio端口,里边有如下属性文件

       direction  表示gpio端口的方向,读取结果是inout。该文件也可以写,写入out 时该gpio设为输出同时电平默认为低。写入lowhigh则不仅可以设置为输出 还可以设置输出的电平。 当然如果内核不支持或者内核代码不愿意,将不会存在这个属性,比如内核调用了gpio_export(N,0)就表示内核不愿意修改gpio端口方向属性 

      

      value   表示gpio引脚的电平,0(低电平)1(高电平),如果gpio被配置为输出,这个值是可写的,记住任何非零的值都将输出高电平, 如果某个引脚能并且已经被配置为中断,则可以调用poll(2)函数监听该中断,中断触发后poll(2)函数就会返回。

                                   

      edge    表示中断的触发方式,edge文件有如下四个值"none", "rising", "falling","both"

          none 表示引脚为输入,不是中断引脚

          rising 表示引脚为中断输入,上升沿触发

          falling 表示引脚为中断输入,下降沿触发

          both 表示引脚为中断输入,边沿触发

       这个文件节点只有在引脚被配置为输入引脚的时候才存在。 当值是none时可以通过如下方法将变为中断引脚

       echo "both" > edge;对于是both,falling还是rising依赖具体硬件的中断的触发方式。此方法即用户态gpio转换为中断引脚的方式

                

      active_low  不怎么明白,也木有用过   

                                                             

 (3)/sys/class/gpio/gpiochipN


      gpiochipN  表示的就是一个gpio_chip,用来管理和控制一组gpio端口的控制器,该目录下存在一下属性文件: 

      

      base   N相同,表示控制器管理的最小的端口编号。 

      lable   诊断使用的标志(并不总是唯一的) 

      ngpio  表示控制器管理的gpio端口数量(端口范围是:N ~ N+ngpio-1 



引脚编号 = 控制引脚的寄存器基数 + 控制引脚寄存器位数

1 暴露GPIO操作接口
[cpp]  view plain  copy
  1. static int gpio_export(int pin)  
  2. {  
  3.     char buffer[BUFFER_MAX];  
  4.     int len;  
  5.     int fd;  
  6.   
  7.     fd = open("/sys/class/gpio/export", O_WRONLY);  
  8.     if (fd < 0) {  
  9.         fprintf(stderr, "Failed to open export for writing!\n");  
  10.         return(-1);  
  11.     }  
  12.   
  13.     len = snprintf(buffer, BUFFER_MAX, "%d", pin);  
  14.     if (write(fd, buffer, len) < 0) {  
  15.         fprintf(stderr, "Fail to export gpio!");  
  16.         return -1;  
  17.     }  
  18.      
  19.     close(fd);  
  20.     return 0;  
  21. }  

2 隐藏GPIO操作接口
[cpp]  view plain  copy
  1. static int gpio_unexport(int pin)  
  2. {  
  3.     char buffer[BUFFER_MAX];  
  4.     int len;  
  5.     int fd;  
  6.   
  7.     fd = open("/sys/class/gpio/unexport", O_WRONLY);  
  8.     if (fd < 0) {  
  9.         fprintf(stderr, "Failed to open unexport for writing!\n");  
  10.         return -1;  
  11.     }  
  12.   
  13.     len = snprintf(buffer, BUFFER_MAX, "%d", pin);  
  14.     if (write(fd, buffer, len) < 0) {  
  15.         fprintf(stderr, "Fail to unexport gpio!");  
  16.         return -1;  
  17.     }  
  18.      
  19.     close(fd);  
  20.     return 0;  
  21. }  

3 配置GPIO方向
[cpp]  view plain  copy
  1. static int gpio_direction(int pin, int dir)  
  2. {  
  3.     static const char dir_str[] = "in\0out";  
  4.     char path[DIRECTION_MAX];  
  5.     int fd;  
  6.   
  7.     snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/direction", pin);  
  8.     fd = open(path, O_WRONLY);  
  9.     if (fd < 0) {  
  10.         fprintf(stderr, "failed to open gpio direction for writing!\n");  
  11.         return -1;  
  12.     }  
  13.   
  14.     if (write(fd, &dir_str[dir == IN ? 0 : 3], dir == IN ? 2 : 3) < 0) {  
  15.         fprintf(stderr, "failed to set direction!\n");  
  16.         return -1;  
  17.     }  
  18.   
  19.     close(fd);  
  20.     return 0;  
  21. }  
    【简单说明】
    【1】dir_str[dir == IN ? 0 : 3], dir == IN ? 2 : 3 如果输入为常数宏IN, 取dir_str[0]=“in”;若输入常数宏为OUT,取dir_str[0]=“out”。此处巧妙的使用了在数组中的“\0”。

4 控制GPIO输出
[cpp]  view plain  copy
  1. static int gpio_write(int pin, int value)  
  2. {  
  3.     static const char values_str[] = "01";  
  4.     char path[DIRECTION_MAX];  
  5.     int fd;  
  6.   
  7.     snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/value", pin);  
  8.     fd = open(path, O_WRONLY);  
  9.     if (fd < 0) {  
  10.         fprintf(stderr, "failed to open gpio value for writing!\n");  
  11.         return -1;  
  12.     }  
  13.   
  14.     if (write(fd, &values_str[value == LOW ? 0 : 1], 1) < 0) {  
  15.         fprintf(stderr, "failed to write value!\n");  
  16.         return -1;  
  17.     }  
  18.   
  19.     close(fd);  
  20.     return 0;  
  21. }  

5 获得GPIO输入
[cpp]  view plain  copy
  1. static int gpio_read(int pin)  
  2. {  
  3.     char path[DIRECTION_MAX];  
  4.     char value_str[3];  
  5.     int fd;  
  6.   
  7.     snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/value", pin);  
  8.     fd = open(path, O_RDONLY);  
  9.     if (fd < 0) {  
  10.         fprintf(stderr, "failed to open gpio value for reading!\n");  
  11.         return -1;  
  12.     }  
  13.   
  14.     if (read(fd, value_str, 3) < 0) {  
  15.         fprintf(stderr, "failed to read value!\n");  
  16.         return -1;  
  17.     }  
  18.   
  19.     close(fd);  
  20.     return (atoi(value_str));  
  21.  

6 GPIO翻转操作
    【main函数】
[cpp]  view plain  copy
  1. int main(int argc, char *argv[])  
  2. {  
  3.     int i = 0;  
  4.     gpio_export(P24);  
  5.   
  6.     gpio_direction(P24, OUT); // GPIO为输出状态  
  7.     for (i = 0; i < 10; i++) {  
  8.         printf("LED Blink\n");  
  9.         gpio_write(P24, i % 2);  
  10.         usleep(500 * 1000);  
  11.     }  
  12.     gpio_write(P24, 0); // 恢复输出低电平  
  13.   
  14.     gpio_unexport(P24);  
  15.     return 0;  
  16. }  
7 其他例子
[cpp]  view plain  copy
  1. int set_io_value_high(int gpio)  
  2. {  
  3.     FILE *fp;  
  4.     char buffer[10];  
  5.     int value;  
  6.     char s[50]="";  
  7.     char s1[50]="";  
  8.     if ((fp = fopen("/sys/class/gpio/export""w")) == NULL)   
  9.     {  
  10.         printf("Cannot open export file.\n");  
  11.         return -1;  
  12.     }  
  13.     fprintf(fp, "%d", gpio);  
  14.     fclose(fp);  
  15.   
  16.     sprintf(s,"/sys/class/gpio/gpio%d/direction",gpio);  
  17.     if ((fp = fopen(s, "rb+")) == NULL)   
  18.     {  
  19.         printf("Cannot open %s.\n",s);  
  20.         return -1;  
  21.     }  
  22.     fprintf(fp, "out");  
  23.     fclose(fp);  
  24.           
  25.     sprintf(s1,"/sys/class/gpio/gpio%d/value",gpio);  
  26.   
  27.     if ((fp = fopen(s1, "rb+")) == NULL)   
  28.     {  
  29.         printf("Cannot open %s.\n",s1);  
  30.         return -1;  
  31.     }  
  32.     strcpy(buffer,"1");  
  33.     fwrite(buffer, sizeof(char), sizeof(buffer) - 1, fp);         
  34.     fclose(fp);  
  35.     return 1;  
  36. }  

[cpp]  view plain  copy
  1. int set_io_value_low(int gpio)  
  2. {  
  3.     FILE *fp;  
  4.     char buffer[10];  
  5.     int value;  
  6.     char s[50]="";  
  7.     char s1[50]="";  
  8.     if ((fp = fopen("/sys/class/gpio/export""w")) == NULL)   
  9.     {  
  10.         printf("Cannot open export file.\n");  
  11.         return -1;  
  12.     }  
  13.     fprintf(fp, "%d", gpio);  
  14.     fclose(fp);  
  15.   
  16.     sprintf(s,"/sys/class/gpio/gpio%d/direction",gpio);  
  17.     if ((fp = fopen(s, "rb+")) == NULL)   
  18.     {  
  19.         printf("Cannot open %s.\n",s);  
  20.         return -1;  
  21.     }  
  22.     fprintf(fp, "out");  
  23.     fclose(fp);  
  24.           
  25.     sprintf(s1,"/sys/class/gpio/gpio%d/value",gpio);  
  26.   
  27.     if ((fp = fopen(s1, "rb+")) == NULL)   
  28.     {  
  29.         printf("Cannot open %s.\n",s1);  
  30.         return -1;  
  31.     }  
  32.     strcpy(buffer,"0");  
  33.     fwrite(buffer, sizeof(char), sizeof(buffer) - 1, fp);         
  34.     fclose(fp);  
  35.     return 1;  
  36.   
  37. }  





  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值