我是靠谱客的博主 称心蜡烛,这篇文章主要介绍Linux下对GPIO的操作控制(基于GPIO子系统)概述GIPO子系统介绍示例:通过GPIO子系统控制LED(GPIOA29)示例:通过GPIO子系统中断读取IO值(GPIOC2),现在分享给大家,希望可以做个参考。
目录
- 概述
- GIPO子系统介绍
- 示例:通过GPIO子系统控制LED(GPIOA29)
- 示例:通过GPIO子系统中断读取IO值(GPIOC2)
概述
以前学习了LED和按键驱动,实际上,在Linux中实现这些设备驱动,有一种更为推荐的方法,就是GPIO子系统和Input子系统。GPIO子系统可以控制IO的初始化、输出高低电平值,读取IO的输入电平;Input子系统处理输入事务,任何输入设备的驱动程序都可以通过Input输入子系统提供的接口注册到内核,利用子系统提供的功能来与用户空间交互。例如控制LED、读取按键、触摸屏、鼠标都可以通过这些子系统接口实现。
GIPO子系统介绍
gpio子系统相关描述可在内核源码 Documentation/gpio 了解。
在/sys/class/gpio目录下展示该子系统设备。如果没有请在编译内核的时候加入 Device Drivers-> GPIO Support ->/sys/class/gpio/… (sysfs interface)。
export 和 unexport:把某个GPIO导出用户空间和取消导出用户空间。
- 例如:echo 19 > export,把GPIO19导出到用户空间。
- GPION,其中N值的计算方式:
假设一组端口有32个GPIO,N=index = GPIOx_y= (x-1)*32 +y;
例如一:GPIOB_6,对应的N值为(2-1)*32+6=38;
例如二:GPIOD_3,对应的N值为(4-1)*32+3=99。
进入子系统设备目录,包含一些常用属性:
direction:gpio端口的方向,内容可以是 in 或者 out;
- 示例:echo out > /sys/class/gpio/pioD3/direction
- 如果写入 low 或者 hight,则不仅设置为输出,还同时设置了输出电平(本小点要了解当前内核是否支持)
value:gpio引脚的电平,0为低电平,非0为高电平。
- 如果配置为输入,则该文件可写;
- 如果配置为中断,则可以调用poll(2)函数监听该中断,中断触发后poll(2)函数就会返回。
edge: 中断的触发方式,该文件有4个值。
- none:输入,非中断
- rising:中断输入,上升沿触发
- falling:中断输入,下降沿触发
- both:中断输入,边沿触发
gpio子系统与led子系统是不同,但是类似。 - led只能输出,gpio能输出也能输入
- gpio输入还支持中断功能
- 使用gpio前,需要从内核空间暴露到用户空间
注意:在用户空间控制使用gpio时,注意不要滥用和内核一些绑定好、已经有合适内核启动的引脚冲突。参考 Documentation/driver-api/gpio/drivers-on-gpio.rst
示例:通过GPIO子系统控制LED(GPIOA29)
system函数进行操作:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16void main(void) { if(access("/sys/class/gpio/pioA29/value",F_OK) != 0) { /*使能LED设备*/ system("echo 29 > /sys/class/gpio/export"); } /*设置LED输出*/ system("echo out > /sys/class/gpio/pioA29/direction"); /*打开LED*/ system("echo '1' > /sys/class/gpio/pioA29/value"); sleep(1); /*关闭LED*/ system("echo '0' > /sys/class/gpio/pioA29/value"); }
文件操作实现:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> int main(void) { FILE *p=NULL; int i=0; p = fopen("/sys/class/gpio/export","w"); fprintf(p,"%d",29); fclose(p); p = fopen("/sys/class/gpio/pioA29/direction","w"); fprintf(p,"out"); fclose(p); for(i=0;i<100;i++) { p = fopen("/sys/class/gpio/pioA29/value","w"); fprintf(p,"%d",1); sleep(1); fclose(p); p = fopen("/sys/class/gpio/pioA29/value","w"); fprintf(p,"%d",0); sleep(1); fclose(p); } p = fopen("/sys/class/gpio/unexport","w"); fprintf(p,"%d",38); fclose(p); return 0; }
示例:通过GPIO子系统中断读取IO值(GPIOC2)
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77#include <stdio.h> #include <fcntl.h> #include <poll.h> #include <unistd.h> /*按键按下时,打按键值*/ int main() { FILE *fp=NULL; /*定义一个文件指针*/ if(access("/sys/class/gpio/pioC2",F_OK) != 0) { /*使能GPIO子系统设备*/ fp=fopen("/sys/class/gpio/export","w"); if(fp == NULL) { perror("open export failrn"); return -1; } fprintf(fp,"%d",66); fclose(fp); } /*设置为输入*/ fp=fopen("/sys/class/gpio/pioC2/direction","w"); if(fp == NULL) { perror("open direction failrn"); return -1; } fprintf(fp,"in"); fclose(fp); /*设置中断触发边沿*/ fp=fopen("/sys/class/gpio/pioC2/edge","w"); if(fp == NULL) { perror("open edge failrn"); return -1; } fprintf(fp,"both"); fclose(fp); /*对IO值进行poll侦听*/ int fd=open("/sys/class/gpio/pioC2/value",O_RDONLY); if(fd<0) { perror("open '/sys/class/gpio/pioC2/value' failed!n"); return -1; } struct pollfd fds[1]; fds[0].fd=fd; fds[0].events=POLLPRI; while(1) { if(poll(fds,1,0)==-1) { perror("poll failed!n"); return -1; } if(fds[0].revents&POLLPRI) { if(lseek(fd,0,SEEK_SET)==-1) { perror("lseek failed!n"); return -1; } char buffer[16]; int len; if((len=read(fd,buffer,sizeof(buffer)))==-1) { perror("read failed!n"); return -1; } buffer[len]=0; printf("%s",buffer); } } }
最后
以上就是称心蜡烛最近收集整理的关于Linux下对GPIO的操作控制(基于GPIO子系统)概述GIPO子系统介绍示例:通过GPIO子系统控制LED(GPIOA29)示例:通过GPIO子系统中断读取IO值(GPIOC2)的全部内容,更多相关Linux下对GPIO内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复