概述
目录
- 概述
- 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函数进行操作:
void 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");
}
文件操作实现:
#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)
#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的操作控制(基于GPIO子系统)概述GIPO子系统介绍示例:通过GPIO子系统控制LED(GPIOA29)示例:通过GPIO子系统中断读取IO值(GPIOC2)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复