用户可以通过文件系统/sys/class/gpio/路径下的文件节点来操作对应的IO口。在/sys/class/gpio/下有个export文件,向export文件写入要操作的GPIO号,使得该GPIO的操作接口从内核空间暴露到用户空间,GPIO的操作接口包括direction和value等,direction控制GPIO输入或者输出模式,而value可控制GPIO的状态或者读取状态,edge是控制中断触发模式。
在开始使用GPIO之前,需要先查询GPIO有没有已经注册,注册了的GPIO有没有用作特殊用途。
cat /sys/kernel/debug/gpio
cat /sys/kernel/debug/pinctrl/pinctrl/pinmux-pins
设置GPIO为输出管脚
echo 36 > /sys/class/gpio/export # 注册GPIO管脚
echo out > /sys/class/gpio/gpio36/direction # 设置GPIO为输出
echo 0 > /sys/class/gpio/gpio36/value # 设置GPIO输出低电平
echo 1 > /sys/class/gpio/gpio36/value # 设置GPIO输出高电平
设置GPIO为输入管脚
echo 36 > /sys/class/gpio/export # 注册GPIO管脚
echo in > /sys/class/gpio/gpio36/direction # 设置GPIO为输入
cat sys/class/gpio/gpio36/value # 读取GPIO电平
用户态使用gpio监听中断
echo in > direction
echo both > edge
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/poll.h>
int main(int argc, char *argv[])
{
char buff[1024];
int gpio_id;
struct pollfd fds[1];
int gpio_fd = open("/sys/class/gpio/gpio508/value", O_RDONLY);
if (gpio_fd == -1)
printf("gpio open");
fds[0].fd = gpio_fd;
fds[0].events = POLLPRI;
int ret = read(gpio_fd, buff, 10);
if (ret == -1)
printf("read");
while (1)
{
ret = poll(fds, 1, -1);
if (ret == -1)
printf("poll");
if (fds[0].revents & POLLPRI)
{
ret = lseek(gpio_fd, 0, SEEK_SET);
if (ret == -1)
printf("lseek");
ret = read(gpio_fd, buff, 10);
if (ret == -1)
printf("read");
printf("get interrupt\n");
}
}
}
在控制台使用 echo 命令将操作的 GPIO 编号 unexport:
echo N > /sys/class/gpio/unexport
tinker board 2s debian系统移植了wiring pi库,用户可以根据自己的喜好选择使用wiring pi库来使用gpio或者使用文件操作方式使用gpio。
gpio readall
+-----+-----+---------+------+---+--Tinker--+---+------+---------+-----+-----+
| CPU | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | CPU |
+-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
| | | 3.3v | | | 1 || 2 | | | 5v | | |
| 252 | 8 | SDA.1 | | 1 | 3 || 4 | | | 5V | | |
| 253 | 9 | SCL.1 | | 1 | 5 || 6 | | | 0v | | |
| 17 | 7 | GPIO0C1 | IN | 1 | 7 || 8 | 1 | SERL | TxD1 | 15 | 161 |
| | | 0v | | | 9 || 10 | 1 | SERL | RxD1 | 16 | 160 |
| 164 | 0 | GPIO5B4 | IN | 1 | 11 || 12 | 0 | | GPIO6A0 | 1 | 184 |
| 166 | 2 | GPIO5B6 | SERL | 1 | 13 || 14 | | | 0v | | |
| 167 | 3 | GPIO5B7 | SERL | 1 | 15 || 16 | 1 | IN | GPIO5B2 | 4 | 162 |
| | | 3.3v | | | 17 || 18 | 1 | IN | GPIO5B3 | 5 | 163 |
| 257 | 12 | MOSI1 | | 0 | 19 || 20 | | | 0v | | |
| 256 | 13 | MISO1 | | 1 | 21 || 22 | 0 | IN | GPIO5C3 | 6 | 171 |
| 254 | 14 | SCLK1 | | 1 | 23 || 24 | 1 | | CE0 | 10 | 255 |
| | | 0v | | | 25 || 26 | 1 | | CE1 | 11 | 251 |
| 233 | 30 | SDA.2 | IN | 1 | 27 || 28 | 1 | | SCL.2 | 31 | 234 |
| 165 | 21 | GPIO5B5 | IN | 1 | 29 || 30 | | | 0v | | |
| 168 | 22 | GPIO5C0 | IN | 1 | 31 || 32 | 1 | PWM | GPIO7C7 | 26 | 239 |
| 238 | 23 | GPIO7C6 | PWM | 1 | 33 || 34 | | | 0v | | |
| 185 | 24 | GPIO6A1 | | 0 | 35 || 36 | 1 | IN | GPIO7A7 | 27 | 223 |
| 224 | 25 | GPIO7B0 | IN | 0 | 37 || 38 | 1 | | GPIO6A3 | 28 | 187 |
| | | 0v | | | 39 || 40 | 0 | | GPIO6A4 | 29 | 188 |
+-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
| CPU | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | CPU |
+-----+-----+---------+------+---+--Tinker--+---+------+---------+-----+-----+
#include <wiringPi.h>
int main(int argc, char * argv[])
{
char i;
wiringPiSetup();
pinMode(26, OUTPUT);
for(i = 0; i < 10; ++i)
{
digitalWrite(26, HIGH);
delay(500);
digitalWrite(26, LOW);
delay(500);
}
digitalWrite(26, HIGH);
return 0;
}
#include <stdio.h>
// Operation of LED D2
#define EXPORT_GPIO "echo 37 > /sys/class/gpio/export"
#define GPIO_OUTPUT "echo out > /sys/class/gpio/gpio37/direction"
#define TURNON_LED "echo 0 > /sys/class/gpio/gpio37/value"
#define TURNOFF_LED "echo 1 > /sys/class/gpio/gpio37/value"
void InitLED()
{
system(EXPORT_GPIO);
system(GPIO_OUTPUT);
}
void TurnOnLED()
{
system(TURNON_LED);
}
void TurnOffLED()
{
system(TURNOFF_LED);
}
int main(void)
{
InitLED();
while(1)
{
TurnOnLED();
sleep(1);
TurnOffLED();
sleep(1);
}
return 0;
}
from periphery import GPIO
import time
LED_Pin = 146 #Physical Pin-32 is GPIO 146
# Open GPIO /sys/class/gpio/gpio73 with output direction
LED_GPIO = GPIO(LED_Pin, "out")
while True:
try:
LED_GPIO.write(True)
time.sleep(0.5)
LED_GPIO.write(False)
time.sleep(0.5)
except KeyboardInterrupt:
LED_GPIO.write(False)
break
except IOError:
print ("Error")
LED_GPIO.close()
sudo python3 gpio.py
import time
def read_40():
with open('/sys/class/gpio/gpio40/value', 'r') as f:
io_40 = int(f.read())
print("read_40:%d"%io_40)
def write_40(io_str):
with open('/sys/class/gpio/gpio40/value', 'w') as f:
f.write(io_str)
print("write_40:%s"%(io_str))
start = time.time()
read_40()
write_40("1")
read_40()
end = time.time()
print("读写IO的时间", end-start)