从单片机过度到有操作系统的板子,我们都是从控制GPIO口点灯开始,今天就说一下linux系统下如何控制GPIO
之前玩一款ARM A9的板子,当时控制GPIO是通过看开发板电路图来查找相应的管脚,再根据手册来修改对应寄存器的值,来控制GPIO,今天来说一下,直接通过控制文件来控制GPIO
我们先进入Linux内核中的此路径下
/sys/class/gpio
这里我们以引脚好为 100 进行创建好删除操作,直接在命令行输入一下命令
创建一个GPIO节点
echo 100 > export
删除一个GPIO节点
echo 100 > export
注意:是在 /sys/class/gpio 路径下执行的
这里是在虚拟机上测试
所以引脚号特别的重要,我们如何将引脚号和对管脚对应。我之前用飞凌的OK1012A开发板
它的 /sys/class/gpio 路径下用这四个文件
查看驱动代码是看到它就加载了两个GPIO分别是GPIO0和GPIOI1,而我查看相关手册引脚就两种GPIO1_x和GPIO2_x
经过测试
GPIO1_x的引脚号=480 + x
GPIO2_x的引脚号=448 + x
注意GPIO1_x和GPIO1[x]代表的是一个GPIO引脚
我们知道GPIO口有输入和输出模式
查看GPIO口的方向,我们进入gpio路径下
cd /sys/class/gpio/gpioxx
查看方向
cat direction
一般就会显示 in 或者 out
方向的设置
输入模式
echo in > direction
输出模式
echo out > direction
如何输入命令报错误,先查看一下你的路径是不是在gpioxx 下
查看GPIOxx的电平输入下面命令
cd /sys/class/gpio/gpioxx
cat value
会显示出 1 (高电平)或者 0(低电平)
我们可以通过下面命令来设置电平
设置为高电平
echo 1 > value
设置为低电平
echo 0 > value
我们一般都是在代码中操作,所有我们可以使用 system这个函数
system("echo 100 > /sys/class/gpio/export");
system("echo out > /sys/class/gpio/gpio100/direction"); //设置为输出模式
system("echo 1 > /sys/class/gpio/gpio100/value"); //设置高电平
还有一种方法就是对文件的操作
#include
#include
#include
#include
int main(void)
{
FILE *p=NULL;
p = fopen("/sys/class/gpio/export","w");
fprintf(p,"%d",100);
fclose(p);
p=fopen("/sys/class/gpio/gpio38/direction","w");
fprintf(p,"out");
fclose(p);
p = fopen("/sys/class/gpio/gpio38/value","w");
fprintf(p,"%d",1);
fclose(p);
return 0;
}
这两种方法都是可以实现的大家根据自己的需求来选择
还有一个用途比较广泛的就是,检测GPIO口的电平来赋值给变量,下面程序大家可以参考
#include
#include
#include
#include
#include //define O_WRONLY and O_RDONLY
//创建gpio文件
void initGpio(int n)
{
FILE * fp =fdopen("/sys/class/gpio/export","w");
if (fp == NULL)
perror("export open filed");
else
fprintf(fp,"%d",n);
fclose(fp);
} //create gpio file
//设置gpio方向
void setGpioDirection(int n,char *direction)
{
char path[100] = {0};
sprintf(path,"/sys/class/gpio/gpio%d/direction",n);
FILE * fp =fdopen(path,"w");
if (fp == NULL)
perror("direction open filed");
else
fprintf(fp,"%s",direction);
fclose(fp);
} //set gpio "in" or "out"
//设置gpio的电平
void set_gpioValue(int n, int value)
{
char path[64];
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", n);
FILE *fp = fopen(path, "w");
if (fp == NULL)
perror("direction open filed");
else
fprintf(fp, "%d", value);
fclose(fp);
}
//获取gpio的值
int getGpioValue(int n)
{
char path[64];
char value_str[3];
int fd;
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", n);
fd = open(path, O_RDONLY);
if (fd < 0) {
perror("Failed to open gpio value for reading!");
return -1;
}
if (read(fd, value_str, 3) < 0) {
perror("Failed to read value!");
return -1;
}
close(fd);
return (atoi(value_str));
} //get gpio(n)'s value
int main()
{
initGpio(18);
setGpioDirection(18,"in");
while(1)
{
printf("%d\n",getGpioValue(18));<span style="white-space:pre"> //每隔1s输出一次gpio18的值
sleep(1);
}
return 0;
}
也可以用shell 命令来测试我们的gpio口
#!/bin/sh
gpio_test(){
GPIO=$1 #注意等号中间不能有空格
echo $GPIO > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio${GPIO}/direction
for i in $(seq 1 3)
do
echo 0 > /sys/class/gpio/gpio${GPIO}/value
sleep 1
echo 1 > /sys/class/gpio/gpio${GPIO}/value
sleep 1
done
echo $GPIO > /sys/class/gpio/unexport
}
#调用函数
gpio_test 898
gpio_test 899