linux IO方式操作gpio
转自http://blog.sina.com.cn/s/blog_7880d3350102w2um.html
http://blog.csdn.net/sukhoi27smk/article/details/26447765
http://blog.csdn.net/xukai871105/article/details/38456079
通过sysfs方式控制GPIO,先访问/sys/class/gpio目录,向export文件写入GPIO编号,使得该GPIO的操作接口从内核空间暴露到用户空间,GPIO的操作接口包括direction和value等,direction控制GPIO方向,而value可控制GPIO输出或获得GPIO输入。文件IO方式操作GPIO,使用到了4个函数open、close、read、write。
首先,看看系统中有没有“/sys/class/gpio”这个文件夹。如果没有请在编译内核的时候加入 Device Drivers-> GPIO Support ->/sys/class/gpio/… (sysfs interface)。
/sys/class/gpio 的使用说明:
gpio_operation 通过/sys/文件接口操作IO端口 GPIO到文件系统的映射
◇ 控制GPIO的目录位于/sys/class/gpio
◇ /sys/class/gpio/export文件用于通知系统需要导出控制的GPIO引脚编号
◇ /sys/class/gpio/unexport 用于通知系统取消导出
◇ /sys/class/gpio/gpiochipX目录保存系统中GPIO寄存器的信息,包括每个寄存器控制引脚的起始编号base,寄存器名称,引脚总数 导出一个引脚的操作步骤
◇ 首先计算此引脚编号,引脚编号 = 控制引脚的寄存器基数 + 控制引脚寄存器位数
◇ 向/sys/class/gpio/export写入此编号,比如12号引脚,在shell中可以通过以下命令实现,命令成功后生成/sys/class/gpio/gpio12目录,如果没有出现相应的目录,说明此引脚不可导出
◇ direction文件,定义输入输入方向,可以通过下面命令定义为输出。direction接受的参数:in, out, high, low。high/low同时设置方向为输出,并将value设置为相应的1/0
◇ value文件是端口的数值,为1或0
几个例子:
1. 导出
/sys/class/gpio# echo 44 > export
2. 设置方向
/sys/class/gpio/gpio44# echo out > direction
3. 查看方向
/sys/class/gpio/gpio44# cat direction
4. 设置输出
/sys/class/gpio/gpio44# echo 1 > value
5. 查看输出值
/sys/class/gpio/gpio44# cat value
6. 取消导出
/sys/class/gpio# echo 44 > unexport
文件读写例程:
#include stdlib.h
#include stdio.h
#include string.h
#include unistd.h
#include fcntl.h //define O_WRONLY and O_RDONLY
//芯片复位引脚: P1_16
#define SYSFS_GPIO_EXPORT "/sys/class/gpio/export"
#define SYSFS_GPIO_RST_PIN_VAL "48"
#define SYSFS_GPIO_RST_DIR "/sys/class/gpio/gpio48/direction"
#define SYSFS_GPIO_RST_DIR_VAL "OUT"
#define SYSFS_GPIO_RST_VAL "/sys/class/gpio/gpio48/value"
#define SYSFS_GPIO_RST_VAL_H "1"
#define SYSFS_GPIO_RST_VAL_L "0"
int main()
{
int fd;
//打开端口/sys/class/gpio# echo 48 > export
fd = open(SYSFS_GPIO_EXPORT, O_WRONLY);
if(fd == -1)
{
printf("ERR: Radio hard reset pin open error.\n");
return EXIT_FAILURE;
}
write(fd, SYSFS_GPIO_RST_PIN_VAL ,sizeof(SYSFS_GPIO_RST_PIN_VAL));
close(fd);
//设置端口方向/sys/class/gpio/gpio48# echo out > direction
fd = open(SYSFS_GPIO_RST_DIR, O_WRONLY);
if(fd == -1)
{
printf("ERR: Radio hard reset pin direction open error.\n");
return EXIT_FAILURE;
}
write(fd, SYSFS_GPIO_RST_DIR_VAL, sizeof(SYSFS_GPIO_RST_DIR_VAL));
close(fd);
//输出复位信号: 拉高>100ns
fd = open(SYSFS_GPIO_RST_VAL, O_RDWR);
if(fd == -1)
{
printf("ERR: Radio hard reset pin value open error.\n");
return EXIT_FAILURE;
}
while(1)
{
write(fd, SYSFS_GPIO_RST_VAL_H, sizeof(SYSFS_GPIO_RST_VAL_H));
usleep(1000000);
write(fd, SYSFS_GPIO_RST_VAL_L, sizeof(SYSFS_GPIO_RST_VAL_L));
usleep(1000000);
}
close(fd);
printf("INFO: Radio hard reset pin value open error.\n");
return 0;
}
另外参考网上一个网友的程序,这里做了验证,并实现中断检测函数。如下:
#include stdlib.h
#include stdio.h
#include string.h
#include unistd.h
#include fcntl.h
#include poll.h
#define MSG(args...) printf(args)
//函数声明
static int gpio_export(int pin);
static int gpio_unexport(int pin);
static int gpio_direction(int pin, int dir);
static int gpio_write(int pin, int value);
static int gpio_read(int pin);
static int gpio_export(int pin)
{
char buffer[64];
int len;
int fd;
fd = open("/sys/class/gpio/export", O_WRONLY);
if (fd < 0) {
MSG("Failed to open export for writing!\n");
return(-1);
}
len = snprintf(buffer, sizeof(buffer), "%d", pin);
if (write(fd, buffer, len) < 0) {
MSG("Failed to export gpio!");
return -1;
}
close(fd);
return 0;
}
static int gpio_unexport(int pin)
{
char buffer[64];
int len;
int fd;
fd = open("/sys/class/gpio/unexport", O_WRONLY);
if (fd < 0) {
MSG("Failed to open unexport for writing!\n");
return -1;
}
len = snprintf(buffer, sizeof(buffer), "%d", pin);
if (write(fd, buffer, len) < 0) {
MSG("Failed to unexport gpio!");
return -1;
}
close(fd);
return 0;
}
//dir: 0-->IN, 1-->OUT
static int gpio_direction(int pin, int dir)
{
static const char dir_str[] = "in\0out";
char path[64];
int fd;
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/direction", pin);
fd = open(path, O_WRONLY);
if (fd < 0) {
MSG("Failed to open gpio direction for writing!\n");
return -1;
}
if (write(fd, &dir_str[dir == 0 ? 0 : 3], dir == 0 ? 2 : 3) < 0) {
MSG("Failed to set direction!\n");
return -1;
}
close(fd);
return 0;
}
//value: 0-->LOW, 1-->HIGH
static int gpio_write(int pin, int value)
{
static const char values_str[] = "01";
char path[64];
int fd;
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", pin);
fd = open(path, O_WRONLY);
if (fd < 0) {
MSG("Failed to open gpio value for writing!\n");
return -1;
}
if (write(fd, &values_str[value == 0 ? 0 : 1], 1) < 0) {
MSG("Failed to write value!\n");
return -1;
}
close(fd);
return 0;
}
static int gpio_read(int pin)
{
char path[64];
char value_str[3];
int fd;
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", pin);
fd = open(path, O_RDONLY);
if (fd < 0) {
MSG("Failed to open gpio value for reading!\n");
return -1;
}
if (read(fd, value_str, 3) < 0) {
MSG("Failed to read value!\n");
return -1;
}
close(fd);
return (atoi(value_str));
}
// none表示引脚为输入,不是中断引脚
// rising表示引脚为中断输入,上升沿触发
// falling表示引脚为中断输入,下降沿触发
// both表示引脚为中断输入,边沿触发
// 0-->none, 1-->rising, 2-->falling, 3-->both
static int gpio_edge(int pin, int edge)
{
const char dir_str[] = "none\0rising\0falling\0both";
char ptr;
char path[64];
int fd;
switch(edge){
case 0:
ptr = 0;
break;
case 1:
ptr = 5;
break;
case 2:
ptr = 12;
break;
case 3:
ptr = 20;
break;
default:
ptr = 0;
}
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/edge", pin);
fd = open(path, O_WRONLY);
if (fd < 0) {
MSG("Failed to open gpio edge for writing!\n");
return -1;
}
if (write(fd, &dir_str[ptr], strlen(&dir_str[ptr])) < 0) {
MSG("Failed to set edge!\n");
return -1;
}
close(fd);
return 0;
}
//GPIO1_17
int main()
{
int gpio_fd, ret;
struct pollfd fds[1];
char buff[10];
unsigned char cnt = 0;
//LED引脚初始化
gpio_export(115);
gpio_direction(115, 1);
gpio_write(115, 0);
//按键引脚初始化
gpio_export(49);
gpio_direction(49, 0);
gpio_edge(49,1);
gpio_fd = open("/sys/class/gpio/gpio49/value",O_RDONLY);
if(gpio_fd < 0){
MSG("Failed to open value!\n");
return -1;
}
fds[0].fd = gpio_fd;
fds[0].events = POLLPRI;
ret = read(gpio_fd,buff,10);
if( ret == -1 )
MSG("read\n");
while(1){
ret = poll(fds,1,0);
if( ret == -1 )
MSG("poll\n");
if( fds[0].revents & POLLPRI){
ret = lseek(gpio_fd,0,SEEK_SET);
if( ret == -1 )
MSG("lseek\n");
ret = read(gpio_fd,buff,10);
if( ret == -1 )
MSG("read\n");
gpio_write(115, cnt++%2);
}
usleep(100000);
}
return 0;
}
linux IO方式操作gpio相关推荐
- TX2 用文件IO的方式操作GPIO
概述 通过 sysfs 方式控制 GPIO,先访问 /sys/class/gpio 目录,向 export 文件写入 GPIO 编号,使得该 GPIO 的操作接口从内核空间暴露到用户空间,GPIO 的 ...
- A40i使用笔记:GPIO操作方式(用于测试设备io驱动性能)(传统方式、设备树方式、寄存器方式操作GPIO)
一.前言 前文介绍了文件io的驱动方式,可以用于led点灯灭灯或者一些简单的不需求时序控制的ic操作,但是用于功能类ic,如AD采集芯片等时序控制需求高的,就不行了,这时候就需求高速io去实现指定的芯 ...
- linux+gpio+嵌入式,嵌入式Linux系统中对GPIO操作的方法总结
在Linux系统里操作GPIO的方法有以下几个: 1. 写驱动的方式 需要自己编写linux驱动,在驱动里操控GPIO,应用通过驱动提供的节点来控制GPIO.优点是结构清晰,可扩展性强,比较灵活.缺点 ...
- sysfs方式控制GPIO
sysfs方式控制GPIO 使用"gpiolib"实现框架的平台可选择配置一个GPIO的sysfs用户接口,这不同于debugfs接口,因为它提供GPIO方向和值的控制,而不仅是显 ...
- linux设备树sysfs,迅为-iMX6开发板-设备树内核-sys方式控制GPIO
本文档主要讲解迅为-iMX6 开发板,通过 sys 文件的方式来控制 GPIO. 要通过 sys 控制 GPIO,需要做以下几步操作: 1 开启内核中的"GPIO_SYSFS"驱动 ...
- [linux]linux IO 5种方式
1.几个重要概念 用户空间与内核空间: 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方).操作系统的核心是内核,独立于普通的应用程序,可以访 ...
- STM32笔记 GPIO介绍及IO口操作 STM32F0 利用C语言位域实现仿位带操作
文章目录 GPIO简介 工作方式 相关寄存器介绍 IO 操作步骤 IO口三种操作细解 附录:C语言相关 偏移地址与绝对地址 GPIO简介 GPIO:每个连接到I/O总线上的设备都有自己的I/O地址集, ...
- Linux下C编程-----IO/文件操作 模拟linux ls程序显示文件系统树形结构(2)
Linux下的IO/文件操作练习,知识虽然简单 但是往往基础容易被忽略,偶尔的练习是有必要的. 练习printf /****************************************** ...
- Linux应用层操作GPIO,查看GPIO状态
1.操作GPIO system("echo 421 >/sys/class/gpio/export"); system("echo out >/sys/cla ...
最新文章
- Hashmap,Set,Map,List,ArrayList的区别
- 偷懒日志 - 自动生成代码 - 第二步 生成POJO
- 如何在Linux中恢复一个删除了的文件
- 渗透工具开发——XSS平台的命令行实现
- datetime插入数据_SQL项目_(一)数据源准备
- 基础练习 十进制转十六进制 C语言
- Spark练习 - 提交作业到集群 - submit job via cluster
- 修改WordPress主题导致整个站点404无法访问
- php默认语法,php基本语法
- gcc生成的汇编和keil生成的汇编_Linux编译工具:gcc入门
- Castle动态代理拦截器可构建可重启的流
- 服务器电源维修哪里便宜,服务器电源维修
- javascript基础知识总结
- c语言中用double写圆的面积,用java写一个函数area,接收一个double类型的参数(表示圆的半径r),用于计算圆的面积...
- java8 numberformat,NumberFormat舍入问题仅限Java 8
- 西点教育计算机二级证,拍了拍你:西式面点师证报名报考政策须知
- win10下conda 使用教程
- 在vm虚拟机上安装esd格式的win7系统文件
- 厚积薄发打卡Day26:狂神说Java之JUC并发编程<代码+笔记>(上)
- 脚手架的这个好搭档 今天要重点来介绍下!
热门文章
- 笛卡尔乘积特征构造以及遗传编程特征构造
- 深入浅出kafka原理-2-Kafka为何那么快(高效)
- 日本“冷知识”你都知道吗?
- 解决IIS中无法运行aspx文件,提示:服务器应用程序不可用
- 软件安全测试-Web安全测试详解-CSRF攻击
- 情人节选什么礼物?盘点最火爆几款礼物
- 微软网盘onedrive|共享网盘程序大全
- android 自定义relativelayout,Android布局(RelativeLayout、TableLayout等)使用方法
- 2016年秋-网络程序设计 学习总结
- 服务器国产自研芯片,国产自研芯片新时代 龙芯A4000评测