• o8_194407
    了解作者
  • 853.3KB
    文件大小
  • 7z
    文件格式
  • 0
    收藏次数
  • VIP专享
    资源类型
  • 0
    下载次数
  • 2022-05-20 08:00
    上传日期
基于开源的https://github.com/HuRuWo/SerialPortHelper工程,修正了一个导致app异常的地方,同时把google serialport api源码也集成到一起,用Android Studio3.4.1版本作为开发工程管理工具,并且在显示接收到的串口数据时,增加了Hex或者gb2312汉字编码显示选择;以及增加了app进入后台或者从后台重新恢复前台的状态监测机制……
SerialPortHelper.7z
内容介绍
# SerialPortHelper Android 串口调试助手 # 前言 物联网开发开发是时下热门的行业。Android系统自然也能进行物联网开发。除开Android本身自带的模块还有一类通过外部链接的设备需要通过串口来进行通信。本人在做完两个相关的抓娃娃和寄存柜项目之后觉得需要总结一点东西给大家。 # 一些预备知识 ## 关于串口 串口通信指[串口](https://baike.baidu.com/item/%E4%B8%B2%E5%8F%A3)按位(bit)发送和接收字节。尽管比按[字节](https://baike.baidu.com/item/%E5%AD%97%E8%8A%82)(byte)的[并行通信](https://baike.baidu.com/item/%E5%B9%B6%E8%A1%8C%E9%80%9A%E4%BF%A1)慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。 在串口通信中,常用的协议包括RS-232、RS-422和RS-485。 当然具体是那种协议和你选择的硬件有关,将你的硬件插到对应协议的串口口即可。 ## 开发前的准备 1.检查你的开发板设备,包括开发板信息,开发板上面包含的模块信息。是否有Wifi模块 蓝牙模块 指定接口等。还有一方面就是关于开发板系统的信息,开发板的系统版本。如果需要特别定制,可以和厂商商量。 >关于系统定制 某些特殊的板块需要隐藏状态栏不能被下拉,否则会被退出应用。还有一方面就是可以定制取消掉下导航栏。 2.检查你的硬件装备 正确连接你的设备,向你的硬件提供商索要开发资料。基本的资料包括硬件的通讯命令格式。当然更好的是如果能要到开发程序资料。比如android程序或者源码那就更好了。 3.正确的连接,测试你的硬件与系统 [Android串口助手](http://zhushou.360.cn/detail/index/soft_id/162355?recrefer=SE_D_%E4%B8%B2%E5%8F%A3%E5%8A%A9%E6%89%8B) 下载一个串口调试助手,按照资料输入命令。测试是否能够成功的启动设备。并且收到对应的返回数据。 # 开发阶段 >需要一点点的JNI知识和一点点Android多线程开发经验 整体的开发流程如下:打开指定串口-->开启接收数据线程(readthead)-->发送串口数据-->接收数据处理返回信息-->关闭接收数据线程(readthead)-->关闭串口。 ## 导入so库 [谷歌开源serialPort api项目 ](https://github.com/cepr/android-serialport-api) 里面封装了c层代码调用底层代码的通信方式,如果你们喜欢改东西的话。可以自己改着玩,不过我觉得没有必要,因为这些代码已经封装的很好了。直接使用即可。 至于通过c代码如何生成相应的so文件,以及如何java层调用c层代码都是很基础的东西啦。 我不想在这里展开大篇幅的讲JNI,因为串口通信其实用的JNI知识不多。 首先把JNI相关代码导入到自己的工程里面: 先看下目录结构吧: ### jni目录 ![TIM截图20180423162725.png](https://upload-images.jianshu.io/upload_images/7149395-d72f58063f410f80.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ### java 目录 ![image.png](https://upload-images.jianshu.io/upload_images/7149395-f8bbfc3d08924e56.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ### SerialPort.java 了解JNI的同学都知道的,这个`SerialPort.h`对应的就是`SerialPort.java`层的native 方法。 这里用两个方法 ``` private native static FileDescriptor open(String path, int baudrate, int flags); public native void close(); ``` 很显然一个是打开串口 一个是 关闭串口 方法 打开串口之前,程序需要获得最高权限,`SerialPort.java`的构造函数里面需要获得设备的超级root权限,也是通过输入su命令完成。 ``` if (!device.canRead() || !device.canWrite()) { try { /* Missing read/write permission, trying to chmod the file */ Process su; su = Runtime.getRuntime().exec("/system/bin/su"); String cmd = "chmod 666 " + device.getAbsolutePath() + "\n" + "exit\n"; su.getOutputStream().write(cmd.getBytes()); if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) { throw new SecurityException(); } } catch (Exception e) { e.printStackTrace(); throw new SecurityException(); } } ``` 最后记得调用生成的.so文件 ``` static { System.loadLibrary("serial_port"); } ``` ### SerialPortFinder 这个类很简单,能用于获取设备的串口信息。通常一个开发板会有几个到十几个的串口。 两个public方法: - `public String[] getAllDevices()` 获取所有串口名称 - `public String[] getAllDevicesPath()` 获取所有串口地址 ## 开始通信 ![image.png](https://upload-images.jianshu.io/upload_images/7149395-7a137e0321109798.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 整个信息发送接收步骤如下: 1.初始化`SerialPort` 获得权限打开指定串口 2.打开`ReadThread`监听数据返回 3.使用`SendThread`发送数据 4.继续发送或者关闭 为此我们需要写一个`SerialHelper`来简化代码,以下是核心代码: **构造函数** ``` public SerialHelper(String sPort, int iBaudRate) { this.sPort = "/dev/ttyS3"; this.iBaudRate = 9600; this._isOpen = false; this._bLoopData = new byte[]{48}; this.iDelay = 500; this.sPort = sPort; this.iBaudRate = iBaudRate; } ``` **打开 关闭 串口** ``` //打开时打开监听线程 public void open() throws SecurityException, IOException, InvalidParameterException { this.mSerialPort = new SerialPort(new File(this.sPort), this.iBaudRate, 0); this.mOutputStream = this.mSerialPort.getOutputStream(); this.mInputStream = this.mSerialPort.getInputStream(); this.mReadThread = new SerialHelper.ReadThread(); this.mReadThread.start(); this.mSendThread = new SerialHelper.SendThread(); this.mSendThread.setSuspendFlag(); this.mSendThread.start(); this._isOpen = true; } // 关闭线程 释放函数 public void close() { if (this.mReadThread != null) { this.mReadThread.interrupt(); } if (this.mSerialPort != null) { this.mSerialPort.close(); this.mSerialPort = null; } this._isOpen = false; } ``` 两个线程 发送线程: ``` private class SendThread extends Thread { public boolean suspendFlag; private SendThread() { this.suspendFlag = true; } public void run() { super.run(); while(!this.isInterrupted()) { synchronized(this) { while(this.suspendFlag) { try { this.wait(); } catch (InterruptedException var5) { var5.printStackTrace(); } } } SerialHelper.this.send(SerialHelper.this.getbLoopData()); try { Thread.sleep((long)SerialHelper.this.iDelay); } catch (InterruptedException var4) { var4.printStackTrace(); } } } public void setSuspendFlag() { this.suspendFlag = true; } public synchronized void setResume() { this.suspendFlag = false; this.notify(); } } ``` 读取线程 ``` private class ReadThread extends Thread { private ReadThread() { } public void run() { super.run(); while(!this.isInterrupted()) { try { if (SerialHelper.this.mInputStream == null) { return; } byte[] buffer = new byte[512]; int size = SerialHelper.this.mInputStream.read(buffer); if (size > 0
评论
    相关推荐