====== GPIO ======
{{page>meta:infobox:wip&noheader&nofooter&noeditbtn}}
阅读 [[wp>General Purpose Input/Output]] 和 [[http://www.mjmwired.net/kernel/Documentation/gpio.txt|GPIO access conventions on Linux]].
* [[docs:guide-user:hardware:mmc_over_gpio]]
* [[toh/tp-link/tl-wr1043nd#GPIOs|GPIOs of AR913x SoC]]
* [[/oldwiki/port.gpio|oldwiki GPIO]]
===== 例子 =====
如果你具备 Arduino 或者其他平台的 GPIO 基本知识,此对于使用 OpenWrt 的 GPIO 将是个好消息。以下我们将以 GPIO29 作为一个开关应用例子。
第一步 在 Linux 中 使 GPIO 有效:
echo "29" > /sys/class/gpio/export
然后你需要决定让 GPIO 作为输入(input)或者输出(output), 本例我们将其作为一个开关使用,所以我们需要输出(ouput)
echo "out" > /sys/class/gpio/gpio29/direction
最后一行,使用 1 或 0 来表示 GPIO 打开(on)或关闭(off):
echo "1" > /sys/class/gpio/gpio29/value
===== 硬件 =====
在路由器设备中 GPIO 通常用在按钮和指示灯中,在最大电流4mA左右时,可以作为源(输出电流)或(吸收阱电流)使用,处于激活状态时电压通常为3.3V。GPIO只有两种可能状态:高或低。此取决于设备定义如何被 GPIO 激活:高激活或者低激活
* **高激活**: 当 GPIO 为高时,设备被激活
* **低激活**: 当 GPIO 为低时,设备被激活
以下图例你可以看到一个 GPIO 连线到一个开关或者 LED 时,其工作状态为低激活或者高激活
\\ \\ {{media:doc:hardware:gpio_high_low.png?600|}}\\ \\
数字电源输出的 5V 信号可以通过使用电压分压器得到一个 3.3V 左右的信号。从路由器的 5V 电源连接至地并且连接到数字电源,数字电源信号输出为 5V 左右,通过电压分压器连接!
\\ \\ {{:media:voltagedividergpio.jpg?600|}}\\ \\
\\ \\ {{:media:5vsignal.jpg?600|}}\\ \\
GPIOs 也可能用于一些复杂的任务:
| ^ 内核模块 ^ 详细描述 ^
| **[[docs:techref:hardware:port.gpio:1-wire]]** | kmod-w1-master-gpio | 1-wire bus master |
| **[[docs:guide-user:hardware:pwm]]** | kmod-pwm-gpio | pulse width modulator |
| **[[docs:techref:hardware:port.gpio:spi]]** | kmod-spi-gpio | bitbanging Serial Peripheral Interface |
| ::: | kmod-mmc-over-gpio | [[docs:guide-user:hardware:mmc_over_gpio|MMC/SD card over GPIO]] |
| **[[docs:techref:hardware:port.i2c|I2C]]** | kmod-i2c-gpio | bitbanging I2C |
| **[[docs:guide-user:hardware:lirc]]** | no module yet | Linux Infrared Remote Control |
| **[[docs:techref:hardware:port.gpio:rotary_encoder]]** | kmod-input-gpio-encoder | GPIO rotary encoder |
==== GPIO 中断 ====
如你需要管理一些高信号频次应用中,使用 GPIO 作为输入,那么 GPIO 中断是非常有用的。如果没有中断,GPIO 输入必须使用**轮询**方法,**轮询**方法是无法用作来处理高信号频次输入应用。
并非所有板载 GPIO 都有中断. 例如 **bcm63xx SoCs 没有 GPIO 中断**,此为其设备按钮采用**轮询**的原因。作为这样的结果,上述列表中的一些输入驱动(input drivers)在其应用板上并不能工作。
===== 软件 =====
Linux 中 GPIOs 可以通过 GPIO SYSFS 接口:**/sys/class/gpio/** 来访问
为了控制 GPIOs, 你可以使用 **gpioctl-sysfs**, 在不使用手动按钮或者 LED 指示的情况下,你也可以键入简单的脚本来控制 GPIOs.
#!/bin/sh
show_usage()
{
printf "\ngpio.sh [in|out []]\n"
}
if [ \( $# -eq 0 \) -o \( $# -gt 3 \) ] ; then
show_usage
printf "\n\nERROR: incorrect number of parameters\n"
exit 255
fi
#doesn't hurt to export a gpio more than once
(echo $1 > /sys/class/gpio/export) >& /dev/null
if [ $# -eq 1 ] ; then
cat /sys/class/gpio/gpio$1/value
exit 0
fi
if [ \( "$2" != "in" \) -a \( "$2" != "out" \) ] ; then
show_usage
printf "\n\nERROR: second parameter must be 'in' or 'out'\n"
exit 255
fi
echo $2 > /sys/class/gpio/gpio$1/direction
if [ $# -eq 2 ] ; then
cat /sys/class/gpio/gpio$1/value
exit 0
fi
VAL=$3
if [ $VAL -ne 0 ] ; then
VAL=1
fi
echo $VAL > /sys/class/gpio/gpio$1/value
===== 找到 PCB 上的 GPIO 引脚 =====
有时你并不知道你的设备 PCB 上在哪儿有物理 GPIO 引脚,在这样的情况下,你可以使用以下小小脚本和一个万用表来找到。
#!/bin/sh
cd /sys/class/gpio
for i in `seq $1 $2`; do
echo $i > export; echo out >gpio$i/direction
done
nums=`seq $1 $2`
while true; do
for i in $nums; do
echo 0 > gpio$i/value
done
sleep 1
for i in $nums; do
echo 1 > gpio$i/value
done
sleep 1
done
- 执行 ''./gpio 0 30'', 其意思为 pin 0 to 30
- 键入 ctrl-c 可以停止脚本, 然后检查已经已创建的 GPIO: ''find /sys/class/gpio/gpio*''
- 重新开始执行脚本,使用万用表测量哪个引脚"闪烁".
- 当你发现一个 GPIO 引脚时,然后从上面 0-30 范围切除一半来继续查找;
- 重复直至你可以确定 gpio 引脚号