Android硬件通信之 GPIO通信

news2024/11/25 13:01:51

一,为什么要和硬件通信

1.1,做软件开发的可能大多只是在手机上做服务器/客户端这种应用,说白了这些只是对数据的处理,对数据做存储和读取,以及分析的工作。

1.2 但随着智能领域的发展,人们已不满足手动去直接接触硬件,毕竟这个过程需要先走到机器跟前,伸出手按下某一个按钮来控制机器某一行为,更多的想要通过一个小小的手机去控制更多的东西,比如控制车,控制灯,控制任何一种机器,甚至远程相隔几千里外去操控机器。这个时候单纯的上层应用已不能实现需求,需要和硬件建立某种持久的联系,方便时刻去控制硬件。

二,GPIO 介绍

2.1 gpio是什么

GPIO(General Purpose I/O Ports)意思为通用输入/输出端口,通俗地说,就是一些引脚,可以通过它们输出高低电平或者通过它们读入引脚的状态-是高电平或是低电平

GPIO是芯片的引脚,管脚是可编程的,可对引脚的工作模式进行设置:输入模式(检测输入信号),输出模式(输出0或1)。可用来做嵌入式开发,驱动开发等等。

2.2 简单的控制灯的示例

如上图,P21这个GPIO口,输出1的时候LED403点亮,输出0或者没有输出的时候,LED403熄灭。需要亮灯灯的时候调用GPIO口拉高的函数,需要熄灯的时候调用GPIO拉低的函数,即可实现控制。函数的操作,最终变成了向这个GPIO的硬件寄存器写入数据,硬件的状态会跟随寄存器的数据改变而改变 

三 GPIO运用实例

3.1 项目背景

用到gpio的是个门禁人脸识别开锁系统,android开发板上运行人脸识别软件,开发板连接开门锁,这个锁跟我们平时的电机锁并无区别,人脸识别成功后,发送gpio指令来控制锁的开关

3.2 gpio运行过程

首先,看看系统中有没有“/sys/class/gpio”这个文件夹。如果没有请在编译内核的时候加入进去:

Device Drivers
—> GPIOSupport
—> /sys/class/gpio/… (sysfsinterface)。

/sys/class/gpio 的使用说明:

1、gpio_operation 通过/sys/文件接口操作IO端口 GPIO到文件系统的映射;

2、控制GPIO的目录位于/sys/class/gpio;

3、 /sys/class/gpio/export文件用于通知系统需要导出控制的GPIO引脚编号,首先给它赋读写权限;
adb shell chmod 0666 /sys/class/gpio/export

4、/sys/class/gpio/unexport 用于通知系统取消导出GPIO引脚编号,首先给它赋读写权限;
adb shell chmod 0666 /sys/class/gpio/export

5、/sys/class/gpio/gpiochipX目录保存系统中GPIO寄存器的信息,包括每个寄存器控制引脚的起始编号base,寄存器名称,引脚总数等。

6、首先需要计算此引脚编号,引脚编号 = 控制引脚的寄存器基数 + 控制引脚寄存器位数(一般平台不同计算方法也不相同,主要根据平台来计算;
查看gpio对应配置:cat /sys/kernel/debug/gpio //这里可以对应计算出gpio号
查看gpio复用或者是否已被申请使用:/sys/kernel/debug/pinctrl/pinctrl-rockchip-pinctrl/pinmux-pins

7、向/sys/class/gpio/export写入此编号,比如12号引脚,在shell中可以通过以下命令实现,命令成功后生成/sys/class/gpio/gpio12目录,如果没有出现相应的目录,说明此引脚不可导出:
echo 12 > /sys/class/gpio/export;

8、direction文件,定义输入输入方向,可以通过下面命令定义为输出,direction接受的参数:in,out, high, low。in/out设置为输入或者输出口,high/low同时设置方向为输出,并将value设置为相应的1/0;

echo out > direction //设置该gpio为输出口

9、value文件是端口的数值,为1或0:为1设置为高电平,为0设置为低电平。
echo 1 > value

adb shell chmod 0666 /sys/class/gpio/export  //export赋权限0666

adb shell chmod 0666 /sys/class/gpio/unexport //unexport赋权限0666

adb shell echo 62 > /sys/class/gpio/export  //通知系统需要导出控制的GPIO62

adb shell chmod 0666 /sys/class/gpio/gpio62/direction //给GPIO62的direction属性赋权限0666

adb shell chmod 0666 /sys/class/gpio/gpio62/value //给GPIO62的value属性赋权限0666

adb shell echo out > /sys/class/gpio/gpio62/direction  //往GPIO62的direction属性写入out,设置GPIO为输出

adb shell echo 1 > /sys/class/gpio/gpio62/value  //往GPIO62的value属性写入1,设置GPIO为高电平
 

四 Runtime.exec()介绍

4.1 Runtime.exec()字面理解运行时执行某种操作,它的主要作用就是调用外部可执行程序或者命令,比如shell命令。通俗讲需要运行JVM外的程序,需要用到Runtime

4.2  执行外部程序命令步骤

​​​​​​​第一步:通过Runtime.getRuntime()获取该类的一个实例,Runtime类是单实例的,每个Java应用程序都有一个该类的实例。

Runtime runtime=Runtime.getRuntime();

​​​​​​​第二步:使用exec方法执行字符串命令并返回一个process对象,process是一个进程,可以做一些进程相关的事情。

Process process =runtime.exec("su");

exect相关方法

// 在单独的进程中执行指定的外部可执行程序的启动路径或字符串命令
public Process exec(String command)
// 在单独的进程中执行指定命令和变量
public Process exec(String[] cmdArray)
// 在指定环境的独立进程中执行指定命令和变量
public Process exec(String command, String[] envp)
// 在指定环境的独立进程中执行指定的命令和变量
public Process exec(String[] cmdArray, String[] envp)
// 在指定环境和工作目录的独立进程中执行指定的字符串命令
public Process exec(String command, String[] envp, File dir)
// 在指定环境和工作目录的独立进程中执行指定的命令和变量
public Process exec(String[] cmdarray, String[] envp, File dir)
// 参数说明:
	cmdarray // 包含所调用命令及其参数的数组。数组第一个元素是命令,其余是参数
	envp	 // 字符串数组,其中每个元素的环境变量的设置格式为 name=value,如果子进程应该继承当前进程的环境,则该参数为null
	dir		 // 子进程的工作目录;如果子进程应该继承当前进程的工作目录,则该参数为null
    
// 参数cmdArray 示例:shutdown -s -t 3600
String arr[] = {"shutdown","-s","-t","3600"};
Process process = Runtime.getRuntime().exec(arr[]);
/*
注意:
	在调用这个方法时,不能将命令和参数放在一起,eg:String arr[] = {"shutdown -s -t 3600"};
	这样会导致程序把“shutdown -s -t 3600”当成是一条命令的名称,然后去查找“shutdown -s -t 3600”这条命令,它当然会找不到,所以就会报错
*/

 

常用方法:

// 导致当前线程等待,如有必要,一直要等到由该 Process 对象表示的进程已经终止。
int waitFor()
/*	如果已终止该子进程,此方法立即返回。
	如果没有终止该子进程,调用的线程将被阻塞,直到退出子进程,0 表示正常终止 */

// 杀掉子进程
void destroy()

// 返回子进程的出口值,值 0 表示正常终止
int exitValue()

// 获取子进程的错误流
InputStream getErrorStream()
// 获取子进程的输入流
InputStream getInputStream()
// 获取子进程的输出流
OutputStream getOutputStream()

第三步:通过 Process实例.getInputStream() 和 Process实例.getErrorStream() 获取的输入流和错误信息流是缓冲池向当前Java程序提供的,而不是直接获取外部程序的标准输出流和标准错误流

而缓冲池的容量是一定的,因此若外部程序在运行过程中不断向缓冲池输出内容,当缓冲池填满,那么外部程序将暂停运行直到缓冲池有空位可接收外部程序的输出内容为止。(采用xcopy命令复制大量文件时将会出现该问题)

所以需要当前的Java程序不断读取缓冲池的内容,从而为腾出缓冲池的空间。

DataOutputStream os = new DataOutputStream(process.getOutputStream());

第四步:输出流发送指令消息 

dataOutputStream.writeBytes(instruct);
dataOutputStream.flush();
dataOutputStream.close();

4.3 示例

public  void chmod(String instruct) {
	try {
		Runtime runtime=Runtime.getRuntime();
		Process process =runtime.exec("su");
		DataOutputStream dataOutputStream = new DataOutputStream(process.getOutputStream());
		dataOutputStream.writeBytes(instruct);
		dataOutputStream.flush();
		dataOutputStream.close();
	} catch (Exception ex) {
		ex.printStackTrace();
	}
}

 五 完成流程Demo示例​​​​​​​

/**
 * 控制门禁锁的打开和关闭
 */
public class GpioEntranceGuardTest {

//gpio引脚编码变量,不同的功能有不同的引脚编码
private  String gpio_number="178";

/**
 * 初始化gpio
 */
public  void gpioInt() {
	//写入编号
	String exportPath = "echo " + gpio_number + " > /sys/class/gpio/export";
	chmod(exportPath);

	//定义输入输出方向
	String directionPath = "echo out > " + " /sys/class/gpio/gpio" + gpio_number
			+ "/direction";
	chmod(directionPath);

	//赋予引脚编号的读写权限
	String permissionGpio = "chmod 0777 /sys/class/gpio/"+gpio_number+"/value";
	chmod(permissionGpio);
}

/**
 * 获取gpio编号对应的值,即是高电屏,或低电平
 * @return
 */
public  int getValue() {
	File localFile = new File("/sys/class/gpio/gpio" + gpio_number
			+ "/value");
	if (!localFile.exists())
		System.out.println(localFile.getAbsoluteFile() + " not exist!");
	while (true) {
		try {
			FileReader localFileReader = new FileReader(localFile);
			char[] arrayOfChar = new char[1];
			int i = localFileReader.read(arrayOfChar, 0, 1);
			localFileReader.close();
			if (i == 1) {
				int j = arrayOfChar[0];
				if (j == 48)
					return 0;
				return 1;
			}
		} catch (FileNotFoundException localFileNotFoundException) {
			localFileNotFoundException.printStackTrace();
			return -1;
		} catch (IOException localIOException) {
			localIOException.printStackTrace();
			return -1;
		}
	}
}

//发送指令,设置gpio值,即设置高电屏,或低电平
public  void setValue(int paramInt) {
	String exportPath1 = "echo " + paramInt + " > /sys/class/gpio/gpio"+gpio_number+"/value";
	chmod(exportPath1);
}

/**
 * 执行外部程序指令
 * @param instruct 指令
 */
public  void chmod(String instruct) {
	try {
		Runtime runtime=Runtime.getRuntime();
		Process process =runtime.exec("su");
		DataOutputStream dataOutputStream = new DataOutputStream(process.getOutputStream());
		dataOutputStream.writeBytes(instruct);
		dataOutputStream.flush();
		dataOutputStream.close();
	} catch (Exception ex) {
		ex.printStackTrace();
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/460035.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

医院核心数据库一体化建设实践

建设背景 “以数据为核心资源的数字化时代,正在成为引领和推动新一轮科技革命的核心力量,将会深刻影响卫生健康行业。” 这是四月份发布的《公立医院运营管理信息化功能指引》中对数据重要性的描述。数据库作为数据的载体,支撑着整个业务系…

李清照最经典的10首诗词

在三千年的诗歌艺术中,男人一直是绝对的主角,虽然时常有女诗人,却如流星闪过。 一直到宋代,李清照的横空出世,给文坛带来一股清风。 她被誉为“千古第一才女”,她的诗词可柔美、可刚毅。 有人将她与李煜…

android studio RadioButton单选按钮

1.定义 <!--单选按钮--> <TextViewandroid:layout_marginTop"10dp"android:layout_width"match_parent"android:layout_height"wrap_content"android:text"请选择你的性别&#xff1a;"> </TextView> <RadioGrou…

3年外包终上岸,我只能说这类公司能不去就不去····

我大学学的是计算机专业&#xff0c;毕业的时候&#xff0c;对于找工作比较迷茫&#xff0c;也不知道当时怎么想的&#xff0c;一头就扎进了一家外包公司&#xff0c;一干就是3年。现在终于跳槽到了互联网公司了&#xff0c;我想说的是&#xff0c;但凡有点机会&#xff0c;千万…

广州华锐互动:超写实3d虚拟数字人为多行业场景赋能

超写实3d虚拟数字人是一种高度逼真的虚拟人物形象&#xff0c;其主要是通过计算机技术对人物形象进行建模、渲染和动画制作&#xff0c;达到和真实人物相似的效果。在现代科技的推动下&#xff0c;超写实3d虚拟数字人已经得到广泛应用。 以下是其常见的实用功能&#xff1a; 商…

20230425-VS2019-在线安装C++17

一、软件环境 windows 10 x64 21H2 19044.2846 最后升级时间&#xff1a;2023-04-25 11:19:33 二、下载VS2019 官方下载&#xff1a; 打开官网&#xff1a; https://visualstudio.microsoft.com/zh-hans/vs/older-downloads 展开VS2019&#xff0c;选择【下载】&#xff…

数据流重定向(>,>>)(<,<<)(2>,2>>)

文章目录 数据流重定向什么是数据流重定向标准输出(>,>>)与标准错误输出(2>,2>>)/dev/null垃圾桶黑洞设备与特殊写法标准输入&#xff1a;<与<< 为什么要使用命令输出重定向呢&#xff1f;案例 数据流重定向 数据流重定向由字面意思来看&#xff0…

本地缓存解决方案Caffeine | Spring Cloud 38

一、Caffeine简介 Caffeine是一款高性能、最优缓存库。Caffeine是受Google guava启发的本地缓存&#xff08;青出于蓝而胜于蓝&#xff09;&#xff0c;在Cafeine的改进设计中借鉴了 Guava 缓存和 ConcurrentLinkedHashMap&#xff0c;Guava缓存可以参考上篇&#xff1a;本地缓…

分布式消息队列Kafka(三)- 服务节点Broker

1.Kafka Broker 工作流程 &#xff08;1&#xff09;zookeeper中存储的kafka信息 ​ 1&#xff09;启动 Zookeeper 客户端。 [zrclasshadoop102 zookeeper-3.5.7]$ bin/zkCli.sh ​ 2&#xff09;通过 ls 命令可以查看 kafka 相关信息。 [zk: localhost:2181(CONNECTED) 2]…

ES6 新特性的let--const 解构赋值--模板字符串--对象相关新特性--箭头函数--综合代码示例

目录 ES6 新特性 ES6 基本介绍 ES6 是什么? let 声明变量 演示 let 的基本使用 注意事项和使用细节 代码演示 : const 声明常量/只读变量 应用实例 注意事项和使用细节 解构赋值 基本介绍 应用实例-数组解构 应用实例-对象解构 模板字符串 基本介绍 应用实例…

一次说透,4大服务性幂等场景架构设计方案!

服务幂等性架构设计 作者: 博学谷狂野架构师GitHub&#xff1a;GitHub地址 &#xff08;有我精心准备的130本电子书PDF&#xff09; 只分享干货、不吹水&#xff0c;让我们一起加油&#xff01;&#x1f604; 防重表实现幂等 对于防止数据重复提交&#xff0c;还有一种解决方案…

delta.io 数据湖 checkpoint是什么

checkpoint的直观表现 插入操作 --- /tmp/delta-table/_delta_log 路径下文件的作用 delta-table 是表名 我执行的操作: INSERT OVERWRITE delta.`/tmp/delta-table` SELECT col1 as id FROM VALUES 7,22; 对应的操作日志: /tmp/delta-table/_delta_log/00000000000000…

PPOCR -训练模型转推理模型遇到的问题

前言 使用PPOCR命令行训练验证码单字位置检测识别模型的情况下&#xff0c;这两个checkpoint训练模型测试图片均没出现问题&#xff0c;但转为inference推理模型的时候&#xff0c;问题来了。 问题1&#xff1a;文字检测的训练模型转为推理模型结果全为空 官方文档中确实有提…

ClickHouse初级

ClickHouse初级 一、ClickHouse的特点1.列式存储2.DBMS的功能3.多样化引擎4.高吞吐写入能力 LSM Tree5.数据分区与线程级并行6.性能对比 二、ClickHouse安装三、数据类型3.1整型3.2浮点型3.3 布尔型3.4 Decimal型3.5 字符串3.6 枚举类型3.7 时间类型3.8 数组 四、表引擎4.1 表引…

Semantic Kernel 知多少 | 开启面向 AI 编程新篇章

在 ChatGPT 火热的当下, 即使没有上手亲自体验&#xff0c;想必也对 ChatGPT 的强大略有耳闻。当一些人在对 ChatGPT 犹犹豫豫之时&#xff0c;一些敏锐的企业主和开发者们已经急不可耐地开展基于 ChatGPT 模型 AI 应用的落地探索。 因此&#xff0c;可以明确预见的是&#xf…

生信刷题之ROSALIND——Part 3

目录 1、Mortal Fibonacci RabbitsProblemSample DatasetSample OutputCodeOutput 2、Overlap GraphsProblemSample DatasetSample OutputCodeOutput 3、Calculating Expected OffspringProblemSample DatasetSample OutputCodeOutput 4、Finding a Shared MotifProblemSample …

TF卡目录显示文件夹变0字节的方法

关于电脑上的目录打不开是什么原因&#xff0c;电脑目录打不开是什么原因这个许多人还不清楚&#xff0c;今天小编来为大家解答目录打不开状况&#xff0c;此刻让好多人一起来瞧瞧吧&#xff01; TF卡目录显示文件夹变0字节的方法 工具/软件&#xff1a;sayRecy 步骤1&#xff…

ref的使用与数组中的最全的使用方法

目录 1.ref的使用 什么是 ref 引用&#xff1f; 使用ref引用组件实例 2. this.$nextTick(cd) 方法 数组中的方法 1.some方法 --- 查找到目标元素后就停止后面的查找 2.every----判断每一项是否都满足要求 3.reduce方法 4. filter()方法 5. map()方法 6. forEach()方法…

2023年第十二届数据技术嘉年华(DTC)资料分享

第十二届数据技术嘉年华&#xff08;DTC 2023&#xff09;已于4月8日在北京圆满落幕&#xff0c;大会围绕“开源融合数智化——引领数据技术发展&#xff0c;释放数据要素价值”这一主题&#xff0c;共设置有1场主论坛&#xff0c;12场专题论坛&#xff0c;68场主题演讲&#x…

低调且强大——JNPF低代码平台

前言 先说说很多人为什么要用低代码平台。大部分的反馈是“懒”&#xff0c;其次就是后台管理这东西吧&#xff0c;来来回回就那些东西&#xff0c;查询/表单/表格/弹窗之类的&#xff0c;加上一些增删改查的逻辑。很多人表示&#xff0c;呆过的公司好几家了&#xff0c;后管的…