0 前言
    本文描写叙述假设通过文件IO sysfs方式控制树莓派 GPIO端口。通过sysfs方式控制GPIO,先訪问/sys/class/gpio文件夹,向export文件写入GPIO编号,使得该GPIO的操作接口从内核空间暴露到用户空间,GPIO的操作接口包含direction和value等,direction控制GPIO方向,而value可控制GPIO输出或获得GPIO输入。
    Linux学习可从应用出发,先不纠结Linux驱动编写,先把Linux给玩起来。
    【同样与不同】
    本文和【EasyARM i.mx28学习笔记——文件IO方式操作GPIO】内容类似,大部分代码同样。通过文件IO操作能够有效地避免平台差异,尽管EasyARM im287平台和树莓派全然不同,可是通过sysfs操作GPIO实现代码大致同样。
    和EasyARM im287不同,此处并没有使用交叉编译工具,有树莓派中的gcc工具链编译链接获得可运行文件,而EasyARM im287并不能这样操作。EasyARM im287採用busybox指令集,这也与树莓派中的debian指令集存在差异。
    【相关博文】
    【代码仓库】
    代码仓库位于bitbucket——rpi-gpio-sysfs ,请使用Hg克隆或者直接下载zip包。请不要使用不论什么版本号的IE浏览器訪问链接,除非你已经知道所使用的IE浏览器符合HTML5标准。推荐使用谷歌或者火狐浏览器訪问,若使用国产双核浏览器请切换到极速模式。
    【原理图示意】
图1 连线示意图
1 暴露GPIO操作接口
static int gpio_export(int pin)
{
char buffer[BUFFER_MAX];
int len;
int fd; fd = open("/sys/class/gpio/export", O_WRONLY);
if (fd < 0) {
fprintf(stderr, "Failed to open export for writing!\n");
return(-1);
} len = snprintf(buffer, BUFFER_MAX, "%d", pin);
if (write(fd, buffer, len) < 0) {
fprintf(stderr, "Fail to export gpio!");
return -1;
} close(fd);
return 0;
}
2 隐藏GPIO操作接口
static int gpio_unexport(int pin)
{
char buffer[BUFFER_MAX];
int len;
int fd; fd = open("/sys/class/gpio/unexport", O_WRONLY);
if (fd < 0) {
fprintf(stderr, "Failed to open unexport for writing!\n");
return -1;
} len = snprintf(buffer, BUFFER_MAX, "%d", pin);
if (write(fd, buffer, len) < 0) {
fprintf(stderr, "Fail to unexport gpio!");
return -1;
} close(fd);
return 0;
}
3 配置GPIO方向
static int gpio_direction(int pin, int dir)
{
static const char dir_str[] = "in\0out";
char path[DIRECTION_MAX];
int fd; snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/direction", pin);
fd = open(path, O_WRONLY);
if (fd < 0) {
fprintf(stderr, "failed to open gpio direction for writing!\n");
return -1;
} if (write(fd, &dir_str[dir == IN ? 0 : 3], dir == IN ? 2 : 3) < 0) {
fprintf(stderr, "failed to set direction!\n");
return -1;
} close(fd);
return 0;
}
    【简单说明】
    【1】dir_str[dir == IN ? 0 : 3], dir == IN ? 2 : 3 假设输入为常数宏IN, 取dir_str[0]=“in”;若输入常数宏为OUT,取dir_str[0]=“out”。此处巧妙的使用了在数组中的“\0”。
4 控制GPIO输出
static int gpio_write(int pin, int value)
{
static const char values_str[] = "01";
char path[DIRECTION_MAX];
int fd; snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/value", pin);
fd = open(path, O_WRONLY);
if (fd < 0) {
fprintf(stderr, "failed to open gpio value for writing!\n");
return -1;
} if (write(fd, &values_str[value == LOW ? 0 : 1], 1) < 0) {
fprintf(stderr, "failed to write value!\n");
return -1;
} close(fd);
return 0;
}
5 获得GPIO输入
static int gpio_read(int pin)
{
char path[DIRECTION_MAX];
char value_str[3];
int fd; snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/value", pin);
fd = open(path, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "failed to open gpio value for reading!\n");
return -1;
} if (read(fd, value_str, 3) < 0) {
fprintf(stderr, "failed to read value!\n");
return -1;
} close(fd);
return (atoi(value_str));
}
6 GPIO翻转操作
    【main函数】
int main(int argc, char *argv[])
{
int i = 0; GPIOExport(POUT);
GPIODirection(POUT, OUT); for (i = 0; i < 20; i++) {
GPIOWrite(POUT, i % 2);
usleep(500 * 1000);
} GPIOUnexport(POUT);
return(0);
}
    【makefile】——此处的代码tab显示可能存在问题,请以代码仓库为主。
# 可运行文件
TARGET=test
# 依赖目标
SRCS=gpio-sysfs.c # 目标文件
OBJS = $(SRCS:.c=.o) # 指令编译器和选项
CC=gcc
CFLAGS=-Wall -std=gnu99 $(TARGET):$(OBJS)
$(CC) -o $@ $^ clean:
rm -rf $(TARGET) $(OBJS) # 连续动作,先清除再编译链接,最后运行
exec:clean $(TARGET)
@echo 開始运行
sudo ./$(TARGET)
@echo 运行结束 # 编译规则 $@代表目标文件 $< 代表第一个依赖文件
%.o:%.c
$(CC) $(CFLAGS) -o $@ -c $<
    【上传树莓派中 编译链接并运行】
    make exec
    makefile中exec目标包含下面一个过程,先清除目标文件和可运行文件,然后进行交叉编译,最后使用超级权限运行可运行文件。
    makefile的使用详见【Linux学习笔记——例说makefile 索引博文
7 总结
【1】树莓派和其它嵌入式Linux开发板存在区别和联系,树莓派同样能够使用sysfs控制GPIO。
【2】树莓派即在其它助剂中交叉编译,也可在平台直接编译。
8 參考资料

树莓派学习笔记——使用文件IO操作GPIO SysFs方式的更多相关文章

  1. APUE学习笔记3_文件IO

    APUE学习笔记3_文件IO Unix中的文件IO函数主要包括以下几个:open().read().write().lseek().close()等.这类I/O函数也被称为不带缓冲的I/O,标准I/O ...

  2. imx6用文件io操作gpio

    具体请参考: http://blog.csdn.net/u014213012/article/details/53140781 这里要注意的是: 要让linux支持文件io方式操作gpio,首先驱动必 ...

  3. linux学习笔记一----------文件相关操作

    一.目录结构 二.文件管理操作命令(有关文件夹操作,使用Tab键自动补全文件名(如果多个默认第一个)) 1.ls 查看目录信息:ls -l 查看目录详细信息(等价于ll 某些系统不支持) 2.pwd ...

  4. go语言学习笔记---读取文件io/ioutil 包

    io/ioutil 包几个函数方法 名称  作用 备注 ReadAll 读取数据,返回读到的字节 slice 1 ReadDir 读取一个目录,返回目录入口数组 []os.FileInfo, 2 Re ...

  5. Linux学习记录--文件IO操作相关系统编程

    文件IO操作相关系统编程 这里主要说两套IO操作接口,各自是: POSIX标准 read|write接口.函数定义在#include<unistd.h> ISO C标准 fread|fwr ...

  6. EasyARM i.mx287学习笔记——通过modbus tcp控制GPIO

    0 前言     本文使用freemodbus协议栈,在EasyARM i.mx287上实现了modbus tcp从机. 在该从机中定义了线圈寄存器.当中线圈寄存器地址较低的4位和EasyARM的P2 ...

  7. 树莓派学习笔记(5):成功实现NAS家庭服务器(流媒体播放、文件共享及下载机)

    转载请注明:@小五义http://www.cnblogs.com/xiaowuyiQQ群:64770604 一.家庭服务器实现的主要功能 1.流媒体播放服务:利用DLNA实现电视.手机.电脑播放其上面 ...

  8. SpringMVC:学习笔记(8)——文件上传

    SpringMVC--文件上传 说明: 文件上传的途径 文件上传主要有两种方式: 1.使用Apache Commons FileUpload元件. 2.利用Servlet3.0及其更高版本的内置支持. ...

  9. 树莓派学习笔记——USB wifi配置指南

    0 前言     树莓派既能够使用有线网络又能够无线网络,假设使用有线网络不方便的话能够借助USB wifi无线网卡让树莓派也插上无线"翅膀". 可是和使用有线网络即插即用的方式不 ...

随机推荐

  1. SMTP邮件传输协议发送邮件和附件(转)

    1.     SMTP 常用命令简介 1). SMTP 常用命令 HELO/EHLO 向服务器标识用户身份 MAIL 初始化邮件传输 mail from: RCPT 标识单个的邮件接收人:常在MAIL ...

  2. 关于PsCreateSystemThread函数

    研究了1天这个...MSDN说的不是很清楚NTSTATUS PsCreateSystemThread(  _Out_      PHANDLE ThreadHandle,  _In_       UL ...

  3. springMVC用法 以及一个简单的基于springMVC hibernate spring的配置

    替代struts 1  web.xml中配置springmvc中央控制器 <?xml version="1.0" encoding="UTF-8"?> ...

  4. ListView中加入Button后,Button的点击事件和ListView的点击事件冲突

    1.在ItemView配置的xml文件里的根节点加入属性android:descendantFocusability="blocksDescendants" 2.在要加入事件的控件 ...

  5. NDK如何调试系统核心动态库(无系统源码的情况)

    版权归薛定諤耗子所有,转载请表明出处. 1,有源码,需要导入符号表 2,没有源码,如何调试 1)运行ndk-gdb:../../ndk-gdb --verbose --launch=com.examp ...

  6. stm32之CAN发送、接收详解

    CAN接收报文并过滤之标识符过滤:(重点.难点) 在CAN协议里,报文的标识符不代表节点的地址,而是跟报文的内容相关的.因此,发送者以广播的形式把报文发送给所有的接收者.节点在接收报文时-根据标识符的 ...

  7. BZOJ 2795: [Poi2012]A Horrible Poem( hash )

    ...字符串hash. 假如长度x是一个循环节, 那么对于任意n(x | n)也是一个循环节. 设当前询问区间[l, r]长度为len = ∏piai, 最终答案ans = ∏piai' ,我们只需枚 ...

  8. BZOJ 2212: [Poi2011]Tree Rotations( 线段树 )

    线段树的合并..对于一个点x, 我们只需考虑是否需要交换左右儿子, 递归处理左右儿子. #include<bits/stdc++.h> using namespace std; #defi ...

  9. Android移动view动画问题

    http://www.cnblogs.com/eoiioe/archive/2012/08/29/2662546.html Android写动画效果不是一般的麻烦,网上找了好久,终于解决了动画的问题, ...

  10. android开发之Intent.setFlags()_让Android点击通知栏信息后返回正在运行的程序

    android开发之Intent.setFlags()_让Android点击通知栏信息后返回正在运行的程序     在应用里使用了后台服务,并且在通知栏推送了消息,希望点击这个消息回到activity ...