NVIDIA Jetson Xavier NX 控制GPIO
前言
在linux系统中以文件io的方式控制GPIO示例,开发板为NVIDIA Jetson Xavier NX,其它公司的开发板也可使用。
一、简介
GPIO09接入蜂鸣器,高电平开启,低电平关闭。
二、代码实例
1.gpio.h
代码如下(示例):
#ifndef GPIO_H
#define GPIO_H
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <unistd.h>
#include <fcntl.h>
#define ON "1" //开启
#define OFF "0" //关闭
#define BUZZER "436" //控制蜂鸣器引脚
#define DIRECTION "out" //方向为输出
class gpio
{
private:
/* data */
public:
gpio(/* args */);
~gpio();
int openGpio(const char *port); //导入gpio
int closeGpio(const char *port); //导出gpio
int readGPIOValue(const char *port,int &level); //读取gpio值
int setGpioDirection(const char *port,const char *direction); //设置gpio方向
int setGpioValue(const char *port,const char *level); //设置gpio值
int setGpioEdge(const char *port,const char *edge); //设置gpio输入模式
};
#endif
2.gpio.cpp
代码如下(示例):
#include "gpio.h"
gpio::gpio(/* args */)
{
}
gpio::~gpio()
{
}
int gpio::openGpio(const char *port)
{
int fd;
const char *path = "/sys/class/gpio/export";
fd = open(path, O_WRONLY);
if(fd == -1)
{
perror("Failed to open gpio! ");
return -1;
}
write(fd, port ,sizeof(port));
close(fd);
return 0;
}
int gpio::closeGpio(const char *port)
{
int fd;
const char *path = "/sys/class/gpio/unexport";
fd = open(path, O_WRONLY);
if(fd == -1)
{
perror("Failed to open gpio! ");
return -1;
}
write(fd, port ,sizeof(port));
close(fd);
return 0;
}
int gpio::readGPIOValue(const char *port,int &level)
{
int fd;
char path[40];
sprintf(path,"/sys/class/gpio/gpio%s/value", port);
fd = open(path, O_RDONLY);
if(fd == -1)
{
perror("Failed to read GPIO value!");
return -1;
}
char value[2];
read(fd,value,1);
level = atoi(value);
return 0;
}
int gpio::setGpioDirection(const char *port,const char *direction)
{
int fd;
char path[40];
sprintf(path, "/sys/class/gpio/gpio%s/direction", port);
fd = open(path, O_WRONLY);
if(fd == -1)
{
perror("Failed to set GPIO direction. ");
return -1;
}
write(fd, direction, sizeof(direction));
close(fd);
return 0;
}
int gpio::setGpioEdge(const char *port,const char *edge)
{
int fd;
char path[40];
sprintf(path, "/sys/class/gpio/gpio%s/edge", port);
fd = open(path, O_WRONLY);
if(fd == -1)
{
perror("Failed to set GPIO edge. ");
return -1;
}
write(fd, edge, sizeof(edge));
close(fd);
return 0;
}
int gpio::setGpioValue(const char *port,const char *level)
{
int fd;
char path[40];
sprintf(path, "/sys/class/gpio/gpio%s/value", port);
fd = open(path, O_RDWR);
if(fd == -1)
{
perror("Failed to set GPIO value! ");
return -1;
}
write(fd, level, sizeof(level));
close(fd);
return 0;
}
int main()
{
gpio *gp = new gpio();
if(gp->openGpio(BUZZER) != 0) //打开GPIO
{
exit(1);
}
usleep(10000); //两次操作之间延时10ms
if(gp->setGpioDirection(BUZZER, DIRECTION) != 0) //设置GPIO方向
{
gp->closeGpio(BUZZER);
exit(1);
}
usleep(10000);
if(gp->setGpioValue(BUZZER, ON) != 0) //设置高电平输出,开启蜂鸣器
{
gp->closeGpio(BUZZER);
exit(1);
}
sleep(1); //保持1s
if(gp->setGpioValue(BUZZER, OFF) != 0) //设置低电平输出,关闭蜂鸣器
{
gp->closeGpio(BUZZER);
exit(1);
}
usleep(10000);
gp->closeGpio(BUZZER); //关闭GPIO
return 0;
}
其实上述代码只是以文件io的形式控制GPIO电平状态,在Linux系统中以键入命令的形式同样可以控制GPIO电平状态。
三、拓展
有一个普遍疑惑的问题是:为何自己实践却没有在系统/sys/class/gpio路径下找到指定端口的的GPIO文件,下面以操作484端口为例,我们来观察系统/sys/class/gpio路径下发生的情况。
命令如下(示例):
test@test-desktop:/sys/class/gpio$ ls
export gpiochip240 gpiochip248 gpiochip288 unexport
test@test-desktop:/sys/class/gpio$ echo 484 > export
test@test-desktop:/sys/class/gpio$ ls
export gpio484 gpiochip240 gpiochip248 gpiochip288 unexport
test@test-desktop:/sys/class/gpio$ echo 484 > unexport
test@test-desktop:/sys/class/gpio$ ls
export gpiochip240 gpiochip248 gpiochip288 unexport
test@test-desktop:/sys/class/gpio$
可见只有在执行了导入指定端口的操作后,gpio484文件 才会被系统动态创建出来,同理,执行导出操作后,gpio484 文件被系统销毁。所以在执行访问目标端口文件的操作之前,你得先导入指定的端口。