GPIO使用
GPIO 是 General Purpose I/O 的缩写,即通用输入输出端口,简单来说就是 MCU/CPU 可控制的引脚,这些引脚通常有多种功能,最基本的是高低电平输入检测和输出,部分引脚还会与主控器的片上外设绑定,如作为串口、I2C、网络、电压检测的通讯引脚。
RK3588 具有 5 个 GPIO 控制器,每个控制器可以控制 32 个 IO,作为 GPIO 功能时,端口行为由GPIO 控制器寄存器配置。Rockchip Pin 的 ID 按照控制器 (bank)+ 端口 (port)+ 索引序号 (pin) 组成。
- 控制器(bank)和 GPIO 控制器数量一致
- 端口固定 A、B、C 和 D,每个端口仅有 8 个索引号,(a=0,b=1,c=2,d=3)
- 索引序号固定 0、1、2、3、4、5、6、7
开发板中预留20pin扩展,相应的接口如下
Net name | NUM | NUM | Net name | ||
---|---|---|---|---|---|
GPIO1_A0_d | GPIO1_A0_3V3 | 1 | 2 | GPIO4_D5_3V3 | GPIO4_D5_d |
GPIO1_A1_d | GPIO1_A1_3V3 | 3 | 4 | GPIO4_D4_3V3 | GPIO4_D4_u |
GPIO1_A2_d | GPIO1_A2_3V3 | 5 | 6 | GPIO4_D3_3V3 | GPIO4_D3_u |
GPIO1_A3_d | GPIO1_A3_3V3 | 7 | 8 | GPIO4_D2_3V3 | GPIO4_D2_u |
GPIO1_B4_u | GPIO1_B4_3V3 | 9 | 10 | GPIO1_C6_1V8 | GPIO1_C6_u |
GND | 11 | 12 | GND | ||
GPIO1_B3_d | GPIO1_B3_3V3 | 13 | 14 | SARADC_VIN2 | 1V8 SARADC in |
GPIO1_B2_d | GPIO1_B2_3V3 | 15 | 16 | VCC3V3_SYS | |
GPIO1_B1_d | GPIO1_B1_3V3 | 17 | 18 | VCC12V_DCIN | |
VCC5V0_SYS | 19 | 20 | VCC12V_DCIN |
GPIO sysfs接口控制
在 Linux 中,最常见的读写 GPIO 方式就是用 GPIO sysfs interface,是通过操作 /sys/class/gpio
目录下的 export 、unexport 、gpio{X}/direction, gpio{X} /value(用实际引脚号替代 {X})
等文件实现的,经常出现 shell 脚本里面。在 kernel 4.8 开始,加入了 libgpiod 的支持;而原有基于 sysfs 的访问方式,将被逐渐放弃。
引脚 | 控制器(bank) | 端口号(port) | 索引序号(pin) | 计算结果 |
---|---|---|---|---|
GPIO1_A0 | 1 | A | 0 | 32x1+8x0+0=32 |
GPIO4_D5 | 4 | D | 5 | 32x4+8x3+5=157 |
GPIO1_B1 | 1 | B | 1 | 32x1+8x1+1=41 |
# 在超级用户权限下操作
# 使能引脚GPIO1_A0
echo 32 > /sys/class/gpio/export
# 设置引脚为输入模式
echo in > /sys/class/gpio/gpio32/direction
# 读取引脚的值
cat /sys/class/gpio/gpio32/value
# 设置引脚为输出模式
echo out > /sys/class/gpio/gpio32/direction
# 设置引脚为低电平
echo 0 > /sys/class/gpio/gpio32/value
# 设置引脚为高电平
echo 1 > /sys/class/gpio/gpio32/value
# 复位引脚
echo 32 > /sys/class/gpio/unexport
libgipo控制
libgpiod 是一种字符设备接口,GPIO 访问控制是通过操作字符设备文件(比如 /dev/gpiodchip0 )实现的,并通过 libgpiod 提供一些命令工具、c 库以及 python 封装。
# 安装 gpiod 命令行工具
sudo apt install gpiod
gpiod 工具的使用方法与 sysfs 接口的不同,gpiod 是以控制器(bank)为单位,然后再详细到端口号(port)和索引号(pin),即 gpiod 使用两个数据确定引脚
引脚 | 控制器(bank) | 端口号(port) | 索引序号(pin) | 计算结果 |
---|---|---|---|---|
GPIO1_A0 | 1 | A | 0 | 1,8x0+0=0 |
GPIO4_D5 | 4 | D | 5 | 4,8x3+5=29 |
GPIO1_B1 | 1 | B | 1 | 1,8x1+1=9 |
# 需要超级用户权限方可操作
# 列出所有的 GPIO 控制器
gpiodetect
# 列出 GPIO1 控制器的引脚情况
gpioinfo 1
# 设置 GPIO1_A0为高电平
gpioset 1 0=1
# 获取 GPIO1_A0 引脚状态
gpioget 1 0
# 监控 GPIO_A0 的状态(相当于输入状态)
gpiomon 1 0
注意
当 GPIO 被占用时,libgpiod 控制会出现“设备繁忙”进而无法使用