GPIO全称: General-Purpose Input/Output(通用输入输出),是一种软件运行期间能够动态配置和控制的通用引脚。在RK平台上,除了部分有专门用途的pin(比如DDR、MIPI等),其他的pin,如果不配置复用的话,默认复用状态都是GPIO。RK的GPIO驱动,对上提供的是Linux下标准的GPIO接口。Linux下有一组用户态操作GPIO的sysfs节点。应用层对GPIO编程主要就是通过操作这几个节点来实现。
下面以操作GPIO2_C0和GPIO4_C3为例进行介绍。这两个GPIO位置如下
测试时将这两个脚短接,如下图所示
“/sys/class/gpio” 下面的节点默认是root权限的。需要在adb或者串口终端执行如下命令获取root权限。
su
修改后效果如下
在通用的Linux框架下面,所有GPIO都是用数字编号的。对于RK平台的芯片,其编号计算方式为
(gpio控制器号-0)*32+(端口号-‘A’)*8+索引序号
GPIO2_C0的控制器号为2,端口号为C,索引序号0,故编号为
(2-0) * 32 + 2 * 8 + 0 = 80
同理GPIO4_C3的编号为147
将GPIO80 GPIO147设置为用户态操作
echo 80 > /sys/class/gpio/export
echo 147 > /sys/class/gpio/export
将GPIO80设置为输出 将GPIO147设置为输入
echo out > /sys/class/gpio/gpio80/direction
echo in > /sys/class/gpio/gpio147/direction
在GPIO80为输出的情形下,设置电平
在GPIO147为输入的情形下,读取其电平,1为高,0为低
GPIO80输出高电平,读取GPIO147电平
echo 1 > /sys/class/gpio/gpio80/value
cat /sys/class/gpio/gpio147/value
GPIO80输出低电平,读取GPIO147电平
echo 0 > /sys/class/gpio/gpio80/value
cat /sys/class/gpio/gpio147/value
取消GPIO80 GPIO147用户态操作
echo 80 > /sys/class/gpio/unexport
echo 147 > /sys/class/gpio/unexport
上述操作流程的结果如下图
android 下可以直接使用JAVA原生读写函数来操作GPIO,但是app没有root权限,需要命令行将这些导出的gpio所属组改为system
echo 80 > /sys/class/gpio/export
echo 147 > /sys/class/gpio/export
chown -R system:system /sys/class/gpio/gpio80/
chown -R system:system /sys/class/gpio/gpio147/
JAVA接口代码如下,此处只需要使用简单的读写函数即可
public static void writeToFile(String fileName, String content) throws IOException {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
writer.write(content);
}
}
public static String readFileToString(String fileName) throws IOException {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return new String(Files.readAllBytes(Paths.get(fileName)), StandardCharsets.UTF_8);
}
return null;
}
public static boolean isFileExists(String filePath) {
if (filePath == null || filePath.isEmpty()) {
return false;
}
File file = new File(filePath);
return file.exists();
}
在上一章节创建的app基础上,增加一个按钮和一个文本框,按下按钮则执行测试程序,先判断gpio80和gpio147是否存在,如存在,则先向gpio80写1,读取gpio147,再向gpio80写0,读取gpio147
button2.setText("gpio test");
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 设置要显示的文字
textDisplay.setText("start gpio test... \n");
if(!isFileExists("/sys/class/gpio/gpio147") || !isFileExists("/sys/class/gpio/gpio80")) {
textDisplay.append("gpio not export... \n");
} else {
try {
writeToFile("/sys/class/gpio/gpio80/direction","out");
writeToFile("/sys/class/gpio/gpio147/direction","in");
writeToFile("/sys/class/gpio/gpio80/value","1");
textDisplay.append("write gpio80 1,read gpio147: "+readFileToString("/sys/class/gpio/gpio147/value")+"\n");
writeToFile("/sys/class/gpio/gpio80/value","0");
textDisplay.append("write gpio80 0,read gpio147: "+readFileToString("/sys/class/gpio/gpio147/value")+"\n");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
});
测试时按下 GPIO TEST 的按钮可以看到如下效果