1 引言

串行接口是一种可以将接受来自CPU的并行数据字符转换为连续的串行数据流发送出去,同时可将接受的串行数据流转换为并行的数据字符供给CPU的器件。串口通信(Serial Communications)是指外设和计算机间,通过数据信号线 、地线、控制线等,按位进行传输数据的一种通讯方式。

2 串口参数

串口中有五个重要的参数:串口设备名称、波特率、奇偶校验位、数据位、停止位。设备名称:串口的名称。Linux下查看串口名称使用 ls -l /dev/ttyS*。波特率:传输速率的参数。波特率表示每秒钟传送的二进制位数。常用的有115200、9600。校验位:在串口通信中一种简单的检错方式,有四种检错方式:偶、奇、高和低,允许无校验位。数据位:通信中实际数据位的参数停止位:用于表示单个包的最后一位。

3 开发流程

由于串口通信过程处于硬件底层,使用串口通信需要在系统层次进行操作,谷歌官方为解决这种困难,使用JNI封装了SerialPort类来帮助开发者简化串口通信。
下载链接:serialPort-api。

3.1 导入SerialPort类

(1)在工程的java文件夹下创建android_serialport_api包,并将下载的SerialPort.java文件放在此包下。

(2)在java目录下创建jni目录,并将Android.mk、Application.mk、gen_SerialPort_h.sh、SerialPort.c、SerialPort.h放至此目录下。

(3)在java目录下创建jnilibs目录,将下载的armeabi、armeabi-v7a、x86拷贝至此目录。

4)在项目的bulid.gradle中添加以下代码:

sourceSets {main { jni.srcDirs = [] }
}

SerialPort源代码:

package android_serialport_api;import android.util.Log;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;public class SerialPort {private static final String TAG = "SerialPort";public FileDescriptor mFd;//输入输出数据流private FileInputStream mFileInputStream;private FileOutputStream mFileOutputStream;public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {//检查访问权限,如果没有读写权限,进行文件操作,修改文件访问权限if (!device.canRead() || !device.canWrite()) {try {//通过挂载到linux的方式,修改文件的操作权限Process su = Runtime.getRuntime().exec("/system/xbin/su");String cmd = "chmod 777 " + device.getAbsolutePath() + "n" + "exitn";su.getOutputStream().write(cmd.getBytes());if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {Log.e("SerialPort", "SerialPort: 没有权限");throw new SecurityException();}} catch (Exception e) {e.printStackTrace();throw new SecurityException();}}//调用本地jni方法打开串口mFd = open(device.getAbsolutePath(), baudrate, flags);if (mFd == null) {//若mFd为空则打开失败 Log.e(TAG, "native open returns null");throw new IOException();}mFileInputStream = new FileInputStream(mFd);mFileOutputStream = new FileOutputStream(mFd);}//获取输入输出流public InputStream getInputStream() {return mFileInputStream;}public OutputStream getOutputStream() {return mFileOutputStream;}// JNI(调用java本地接口,实现串口的打开和关闭)// path参数为串口路径,对应linux系统下串口的描述// baudrate 设置的波特率private native static FileDescriptor open(String path, int baudrate, int flags);//本地jni方法关闭串口public native void close();//加载jni下的C文件库static {Log.d(TAG, "本地库加载中");System.loadLibrary("serial_port");}
}

3.2 打开串口

打开串口操作在SerialPort的构造函数中完成,只需创建SerrialPort对象即可打开串口。

private String path = "/dev/ttyMT0";private int baudrate = 115200;serialPort = new SerialPort(new File(path),baudrate,0);if (serialPort == null){Log.e(TAG, "串口打开失败");}

3.3 发送数据

若要通过串口发送数据需要获取串口输出流,发送代码如下:

//获取输出数据流
outputStream = serialPort.getOutputStream();
//发送数据sendData,类型为字节数组
outputStream.write(sendData);
//刷新缓冲区
outputStream.flush();

3.4 接收数据

从串口接收需要获取串口输入流,并且读取数据需要单独开启线程,代码如下:

inputStream = serialPort.getInputStream();/*** 单开一线程,来读数据*/private class ReadThread extends Thread{@Overridepublic void run() {super.run();//判断进程是否在运行,更安全的结束进程while (!threadStatus){byte[] buffer = new byte[1024];int size; //读取数据的大小try {size = inputStream.read(buffer);if (size > 0){Log.e(TAG, "读取的数据数目 = " + size);}} catch (IOException e) {Log.e(TAG, "run: 数据读取异常:" +e.toString());}}}}

3.5 关闭串口

关闭串口之前需要先关闭数据的输入输出流,在调用close方法关闭串口,代码如下:

inputStream.close();
outputStream.close();
serialPort.close();

4 结语

通过上述过程可以实现对于串口的通信过程,为便于串口操作,可以封装SerialPortUtils类来辅助操作窗口:

SerialPortUtils.java:

import android.util.Log;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android_serialport_api.SerialPort;public class SerialPortUtils {private final String TAG = "SerialPortUtils";//串口路径private String path = "/dev/ttyMT0";//设置波特率private int baudrate = 115200;public boolean serialPortStatus = false; //是否打开串口标志public String data;public boolean threadStatus; //线程状态,为了安全终止线程public SerialPort serialPort = null;public InputStream inputStream = null;public OutputStream outputStream = null;/*** 打开串口* @return serialPort串口对象*/public SerialPort openSerialPort(){try {serialPort = new SerialPort(new File(path),baudrate,0);this.serialPortStatus = true;threadStatus = false; //线程状态//获取打开的串口中的输入输出流,以便于串口数据的收发inputStream = serialPort.getInputStream();outputStream = serialPort.getOutputStream();new ReadThread().start(); //开始线程监控是否有数据要接收} catch (IOException e) {Log.e(TAG, "openSerialPort: 打开串口异常:" + e.toString());return serialPort;}Log.d(TAG, "openSerialPort: 打开串口");return serialPort;}/*** 关闭串口*/public void closeSerialPort(){try {inputStream.close();outputStream.close();this.serialPortStatus = false;this.threadStatus = true; //线程状态serialPort.close();} catch (IOException e) {Log.e(TAG, "closeSerialPort: 关闭串口异常:"+e.toString());return;}Log.d(TAG, "closeSerialPort: 关闭串口成功");}/*** 发送串口指令(字符串)* @param data String数据指令*/public void sendSerialPort(String data){Log.e(TAG, "sendSerialPort: 发送数据");try {byte[] sendData = data.getBytes(); //string转byte[]this.data = new String(sendData); //byte[]转stringif (sendData.length > 0) {outputStream.write(sendData);outputStream.flush();Log.e(TAG, "sendSerialPort: 串口数据发送成功");}} catch (IOException e) {Log.e(TAG, "sendSerialPort: 串口数据发送失败:"+e.toString());}}/*** 单开一线程,来读数据*/private class ReadThread extends Thread{@Overridepublic void run() {super.run();//判断进程是否在运行,更安全的结束进程while (!threadStatus){Log.e(TAG, "进入线程run");//64   1024byte[] buffer = new byte[1024];int size; //读取数据的大小try {size = inputStream.read(buffer);Log.e(TAG, "size = " + size);if (size > 0){}} catch (IOException e) {Log.e(TAG, "run: 数据读取异常:" +e.toString());}}}}
}

我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。相信它会给大家带来很多收获:

上述【高清技术脑图】以及【配套的架构技术PDF】可以私信我【666】免费获取,技术问题私信我【999】免费解答。

codesys中打开linux端的串口_干货分享——安卓串口通信相关推荐

  1. codesys中打开linux端的串口_CODESYS版本3.5 SP14 Patch 3发布

    此版本有以下内容更新 主要功能概述: CODESYS Engineering 改进了智能输入辅助.监视列表.监视. CPU负载.编译调试等; 新的数据类型:LREAL或REAL中的__VECTOR [ ...

  2. 在命令行中打开远程端的图形应用程序

    X server是Linux系统里面图形接口服务器的简称.比较常见的Linux界面操作环境有KDE和GNOME,为它们提供系统支持的就是X server,而并非Linux核心. 介绍两种方法在命令行中 ...

  3. lwip协议栈优化_干货分享 | KNI性能优化实践

    友情提示:全文5000多文字,预计阅读时间15分钟 文章源自现网实践对支撑及用户态/内核态网络报文交换场景的认识,欢迎有Linux/FreeBSD内核.网络协议栈.DPDK优化实践经验的同学留言探讨- ...

  4. vs code vue插件_干货分享 | Vue框架常见问题浅谈

    友情提示:全文7800多文字,预计阅读时间10分钟 Vue是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视图层,不仅易于上手, ...

  5. 达梦数据库删除用户_干货分享丨DM8用户管理

    原标题:干货分享丨DM8用户管理 用户介绍 安装创建达梦企业版数据库后,系统会默认创建四类数据库账号,分别是: SYS:达梦数据库内置管理用户,不能登录,数据库使用的大部分的数据字典和动态性能视图. ...

  6. sysdba 默认密码_干货分享|DM数据库密码策略和登录限制设置

    在数据库的用户安全中,口令复杂度策略和资源限制是用户安全重要的一部分.在DM数据库中,口令策略分为系统口令策略和用户口令策略.只有安全版本才支持对每个用户设置口令策略(即用户口令策略),非安全版本,只 ...

  7. python怎么模拟浏览器交互_干货分享:python爬虫模拟浏览器的两种方法实例分析(赶紧收藏)...

    今天为大家带来的内容是:干货分享:python爬虫模拟浏览器的两种方法实例分析(赶紧收藏) 文章主要介绍了python爬虫模拟浏览器的两种方法,结合实例形式分析了Python爬虫模拟浏览器的两种常见操 ...

  8. eureka 之前的服务如何关闭_干货分享 | 服务注册中心Spring Cloud Eureka部分源码分析...

    友情提示:全文13000多文字,预计阅读时间10-15分钟 Spring Cloud Eureka作为常用的服务注册中心,我们有必要去了解其内在实现机制,这样出现问题的时候我们可以快速去定位问题.当我 ...

  9. android分享文件分享结果_干货分享丨DM删除归档日志文件的多种方法

    上一期我们讲解了DM数据库归档日志的切换,本期我们讲解DM数据库归档日志文件的删除. 本章内容已在如下环境上测试: ①操作系统:中标麒麟7: ②数据库版本:达梦8: 相关关键字:DM数据库.归档日志文 ...

最新文章

  1. TP-GAN 让图像生成再获突破,根据单一侧脸生成正面逼真人脸
  2. 1.8 Collections类操作集合详解——排序,查找,复制
  3. 最好用的微型计算机,《微型计算机原理及应用》试题及答案 好
  4. 2017.6.12 crash的数字表格 思考记录
  5. AngularJS表单操作几个例子(表单提交,表单编辑默认值)
  6. 解决Mac Chrome打开HTTPS证书错误问题
  7. MySql Binlog初识
  8. 修改Oracle密码
  9. 打印机质量测试软件,打印机断针测试软件
  10. http 报文格式、状态码
  11. 7 爬虫 CrawlSpider类 增量式爬虫 分布式爬虫 生产者消费者模式
  12. python自动提交网页表单_Python 自动化表单提交实例代码
  13. 一部手机最长能用几年?
  14. UG二次开发GRIP刻字
  15. 北京 Beijing
  16. JavaScript 实现 标签页 切换效果
  17. 免费LOGO在线生成
  18. 1225:金银岛 题解
  19. 如何搭建视频通信服务器架构
  20. 基于社交系统ThinkSNS搭建校园社交系统

热门文章

  1. Arrays.sort() 为什么可以对 int 等数组进行排序?我跟面试官扯了半个小时 | 原力计划...
  2. 我通过了 Google 技术面试,所以你也能行!
  3. 从 Pod 到案例,给小白的 Kubernetes 技术课
  4. 计算机界 TOP 3 难题:“相等”是软件工程中许多重大问题的根源!
  5. 在家远程办公效率低?那你一定要收好这个「在家办公」神器!
  6. 知乎热议!学完 Python 之后,我的编程能力竟然退化了!
  7. 微信回应 iOS 13.2 杀后台;谷歌以 21 亿美元收购 Fitbit;优麒麟 19.10.1 发布 | 极客头条...
  8. 保温杯都这么给力了,你的 Bug 就不能少点?
  9. 即使在微软 Azure 上,Linux 也大有一统天下之势!
  10. 中国如何在 AI 芯片实现弯道超车?