在Linux系统里操作GPIO的方法有以下几个:

1. 写驱动的方式

需要自己编写linux驱动,在驱动里操控GPIO,应用通过驱动提供的节点来控制GPIO。优点是结构清晰,可扩展性强,比较灵活。缺点是实现的过程比较繁琐。

编写驱动可能会用到的kernel函数:

检查GPIO是不是有效的:

int gpio_is_valid(int number);

设备GPIO的方向(输入/输出):

/* set as input or output, returning 0 or negative errno */

int gpio_direction_input(unsigned gpio);

int gpio_direction_output(unsigned gpio, int value);

请求GPIO的资源:

/* request GPIO, returning 0 or negative errno.

* non-null labels may be useful for diagnostics.

*/

int gpio_request(unsigned gpio, const char *label);

清除GPIO资源:

/* release previously-claimed GPIO */

void gpio_free(unsigned gpio);

读取GPIO的状态:

/* GPIO INPUT:  return zero or nonzero */

int gpio_get_value(unsigned gpio);

设备GPIO的状态:

/* GPIO OUTPUT */

void gpio_set_value(unsigned gpio, int value);

详情请参考linuxdir/documentation/gpio.txt

2. 通过linux提供的用户空间

通过在用户空间上来操作GPIO,控制入口在:/sys/class/gpio/。不过需要打开kernel中的相应的选项:Device Drivers->GPIO Support->/sys/class/gpio/... (sysfs nterface)。

优点是简单方便,缺点是可扩展性差。

往export中写入GPIO的号,将会打开Kernel提供的GPIO的用户空间入口。

例如:  "echo 19 > export" 将会创建一个 "gpio19" 的文件夹。

往unexport文件中写入GPIO号,将会关闭之前用export打开的入口。

例如:  "echo 19 > unexport" 将会回收"gpio19"的文件夹。

GPIO文件夹中的属性有以下几个(如/sys/class/gpio/gpio19)

/sys/class/gpio/gpioN/

"direction" 用来设置或读取GPIO的方向。可以设置成"in" 或者 "out".

"value" 用来设置或读取GPIO的值:0或者1. "echo 1 > value"将会把GPION设置成高电平。

"edge" 用来设置中断类型。可以是"none", "rising", "falling", 或者

"both". 只有中断类型可以配置的GPIO才会有这个属性。

"active_low" 设置低电平有效。可以是0或1。

详情请参考linuxdir/documentation/gpio.txt

3. 直接操作/dev/mem

可以直接对/dev/mem节点的内存进行读写来操作GPIO。不过需要参考CPU的datasheet,找到相应的GPIO的寄存器地址。

优点是方便,灵活,缺点是GPIO的寄存器地址不易得到。

下面的函数可以得到GPIO的起始地址,然后可以参考datasheet,对GPIO的方向,功能,和值进行设备。只需要对下面函数中得到的gpio的地址进行操作即可。

int GPIOSetup()

{

int fd = -1;

if ((fd = open ("/dev/mem", O_RDWR | O_SYNC) ) < 0)

{

printf ("wiringPiSetup: Unable to open /dev/mem: %s\n", strerror (errno)) ;

return 0;

}

// GPIO:

gpio = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE) ;

if ((int32_t)gpio == -1)

{

printf("wiringPiSetup: mmap (GPIO) failed: %s\n", strerror (errno)) ;

return 0;

}

return 1;

}

这个是完整的程序,是在基于Raspberry Pi的平台上进行操作的。

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define BCM2708_PERI_BASE                     0x20000000

#define GPIO_BASE (BCM2708_PERI_BASE + 0x00200000)

#define BLOCK_SIZE (4*1024)

#define INPUT 0

#define OUTPUT 1

#define LOW 0

#define HIGH 1

static volatile uint32_t *gpio ;

static uint8_t gpioToGPSET [] =

{

7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,

8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,

} ;

// gpioToGPCLR:

// (Word) offset to the GPIO Clear registers for each GPIO pin

static uint8_t gpioToGPCLR [] =

{

10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,

11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,

} ;

// gpioToGPFSEL:

// Map a BCM_GPIO pin to it's Function Selection

// control port. (GPFSEL 0-5)

// Groups of 10 - 3 bits per Function - 30 bits per port

static uint8_t gpioToGPFSEL [] =

{

0,0,0,0,0,0,0,0,0,0,

1,1,1,1,1,1,1,1,1,1,

2,2,2,2,2,2,2,2,2,2,

3,3,3,3,3,3,3,3,3,3,

4,4,4,4,4,4,4,4,4,4,

5,5,5,5,5,5,5,5,5,5,

} ;

// gpioToShift

// Define the shift up for the 3 bits per pin in each GPFSEL port

static uint8_t gpioToShift [] =

{

0,3,6,9,12,15,18,21,24,27,

0,3,6,9,12,15,18,21,24,27,

0,3,6,9,12,15,18,21,24,27,

0,3,6,9,12,15,18,21,24,27,

0,3,6,9,12,15,18,21,24,27,

} ;

int GPIOSetup()

{

int fd = -1;

if ((fd = open ("/dev/mem", O_RDWR | O_SYNC) ) < 0)

{

printf ("wiringPiSetup: Unable to open /dev/mem: %s\n", strerror (errno)) ;

return 0;

}

// GPIO:

gpio = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE) ;

if ((int32_t)gpio == -1)

{

printf("wiringPiSetup: mmap (GPIO) failed: %s\n", strerror (errno)) ;

return 0;

}

return 1;

}

int GPIOSetPinMode(int nPin, int mode)

{

int    fSel = 0, shift = 0;

fSel    = gpioToGPFSEL [nPin] ;

shift   = gpioToShift  [nPin] ;

if (mode == INPUT)

*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) ; // Sets bits to zero = input

else if (mode == OUTPUT)

*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (1 << shift) ;

return 0;

}

int GPIOSetPin(int nPin, int value)

{

if (value == LOW)

*(gpio + gpioToGPCLR [nPin]) = 1 << (nPin & 31) ;

else

*(gpio + gpioToGPSET [nPin]) = 1 << (nPin & 31) ;

}

linux+gpio+嵌入式,嵌入式Linux系统中对GPIO操作的方法总结相关推荐

  1. linux 软键盘输入密码,Linux_Linux系统中使用屏幕键盘的方法,屏幕键盘可以作为实体键盘输 - phpStudy...

    Linux系统中使用屏幕键盘的方法 屏幕键盘可以作为实体键盘输入的替代方案.在某些时候,屏幕键盘显得非常需要. 比如, 你的键盘刚好坏了:你的机器太多,没有足够的键盘:你的机器没有多余的接口来连接键盘 ...

  2. 移动硬盘里的linux系统文件夹加密,在Deepin系统中加密移动存储设备的方法

    本文介绍简单可行的方法让你在Deepin系统中加密你的移动存储设备,包括U盘及移动硬盘.同时要指出的是虽然可以采用下面方法保护数据不让他人随意观看,但是不能阻止他人破坏数据,例如,格式化U盘或移动硬盘 ...

  3. dragon编译linux,在Linux系统中安装Alibaba Dragonwell8的方法

    本文介绍在Linux系统中安装Alibaba Dragonwell8的方法,包括更新方法.它是阿里巴巴自己的JDK,是OpenJDK的下游版本,完全开源.以下在Ubuntu 18.04上经过了测试,也 ...

  4. 在linux终端中重命名文件,Linux系统中重命名文件的方法有哪些

    今天小编要跟大家分享的文章是关于Linux系统中重命名文件的方法有哪些.正在从事Linux运维工作和学习Linux运维知识的小伙伴们来和小编一起看一看吧,希望本篇文章能够对大家有所帮助. 在Linux ...

  5. 多linux系统的安装方法,在Linux系统中安装使用WPS的方法

    这篇文章主要介绍了在Linux系统中安装使用WPS的方法,在Linux上缺少微软的office的情况下,WPS实为办公文件处理的不二选择,需要的朋友可以参考下 Kingsoft Office 是一套办 ...

  6. linux centos查看用户列表,查看centos中的用户和用户组_Centos查看系统中用户和用户组的方法...

    最近朋友刚接触Linux系统,想要查看系统中都又哪些用户和用户所属的组,接下来吾爱编程就为大家介绍一下Centos查看系统中用户和用户组的方法,有需要的小伙伴可以参考一下: 1.查看系统中的用户: C ...

  7. 在 Linux 系统中查找 MAC 地址的方法

    参考文章: 多种方法在Linux上找到MAC地址 引言: MAC(Media Access Control)地址是网络设备(如网卡)的唯一标识符,用于在局域网中进行通信.在 Linux 系统中,有几种 ...

  8. Debian系统中字体发虚的处理方法

    linux下debian系统中字体虚的处理方法 问题表象: 解决办法: 小插曲: 正经的问题(浏览器字体虚的问题): 上述字体链接下载地址: 问题表象: 最近在使用龙芯电脑安装debian环境中使用3 ...

  9. mysql2008安装虚拟机_在虚拟机xp系统中安装SQL Server2008的方法

    许多用户会使用虚拟机安装xp系统来使用,而有时候不想在主机中安装一些软件,那么在虚拟机中安装就是最好的选择,比如有用户想要在虚拟机xp系统中安装SQL Server2008,但是却不知道要怎么操作,现 ...

  10. 计算机辅助发音,计算机辅助语言学习系统中的发音质量评价方法

    1.本发明提出的一种计算机辅助语言学习系统中语音发音质量评价方法,包括:匹配分数计算.基于美尔(Mel)频标的听感知分数计算.基音分数计算.分数映射.分数融合各部分,具体计算包括以下步骤: 步骤(1) ...

最新文章

  1. GridView标题行换行之我见 (转)
  2. python双星号什么运算_python – 双星号
  3. Python中的range和xrange区别
  4. usb 由于计算机限制,电脑usb被限制了怎么办
  5. SEO十心要诀 细节决定成败
  6. JAVA正则表达式介绍和使用
  7. java获取classpath以外的路径
  8. mysql hammerdb,[料理佳餚] 用 HammerDB 來執行資料庫 TPC-C 效能量測
  9. js中函数参数值传递和引用传递
  10. 安利个数据库工具dbeaver
  11. Twaver-HTML5基础学习(33)自动布局
  12. poj 3345 Bribing FIPA 树形dp
  13. matlab主成分分析代码
  14. 《富爸爸穷爸爸 》 读书笔记
  15. 鸡啄米C++编程入门教程系列
  16. Vue Cli webpack打包出现Waring :Critical dependency: the request of a dependency is an expression
  17. 【已解决】数据库常见场景应用计算次日留存率
  18. 面试篇1:嵌入式C语言面试常见问题
  19. U811.1接口EAI系列之二--生成销售出库单调用U8的EAI通用处理方法--PowerBuilder语言...
  20. 使用Python快速生成二维码的两种方式及二维码解码

热门文章

  1. 集成产品开发团队的管理和决策
  2. java底层 文件操作,java底层是怎的对文件操作的
  3. 为什么我会觉得SegmentFault做得越来越力不从心了?
  4. Unity 官方教程 学习
  5. 智慧城市发展路径中 中国特色是主色调
  6. 《Storm技术内幕与大数据实践》一第1章 绪论
  7. 阿里云负载均衡升级:同城容灾进一步提升可用性
  8. Navigation + Tab Bar 常用组合框架
  9. jQuery - Ajax解决跨域问题
  10. 上週末去南投玩了一下,順便拍了几张,拿出来和大家分享