当前位置: 首页 > news >正文

Android OTG之USB转串口模块通讯

 

微信公众号:CodingAndroid
CSDN:http://blog.csdn.net/xinpengfei521

1.背景简介

我们公司开发了一款室内机平板APP应用,要求平板能去控制智能门锁、等其他智能设备,智能门锁不是我们公司开发的,与我们公司属于合作关系。

2.分析及实现思路

  1. 智能门锁的控制是通过使用 433射频(不了解的请百度)来进行通讯的;
  2. 平板是没法与智能门锁直接进行通讯,但是厂家提供了一个433通讯模块(支持串口);
  3. 而平板(支持OTG)是支持USB转串口模块的,所以整个流程是可以走通的,如下图

3.主要代码实现

3.1初始化USB转串口模块

由于我们选用的是CH340模块,我们先导入ch340的 jar 包,然后在代码中检查手机/平板是否支持USB HOST模式,如果支持我们就初始化通讯时的相关参数:波特率、数据位、停止位等,具体的参数看你们之间通讯的协议。初始化完成之后,我们就可以打开USB进行通讯了,同时初始化完成之后我们需要开启一个读取数据的线程,这样,一旦收到数据或者相应的响应包(一般也叫ACK)我们就可以进行相应的处理了。

下面贴上初始化、及开启读取数据线程的代码实现:

 1    /**
2 * initialize ch340 parameters.
3 *
4 * @param context Application context.
5 */

6 public static void initCH340(Context context) {
7 if (context == null) return;
8 Context appContext = context.getApplicationContext();
9 mUsbManager = (UsbManager) appContext.getSystemService(Context.USB_SERVICE);
10 if (mUsbManager != null) {
11 HashMap<String, UsbDevice> deviceHashMap = mUsbManager.getDeviceList();
12 for (UsbDevice device : deviceHashMap.values()) {
13 if (device.getProductId() == 29987 && device.getVendorId() == 6790) {
14 mUsbDevice = device;
15 if (mUsbManager.hasPermission(device)) {
16 loadDriver(appContext, mUsbManager);
17 } else {
18 if (listener != null) {
19 listener.result(false);
20 }
21 }
22 break;
23 }
24 }
25 }
26 }
27 /**
28 * load ch340 driver.
29 *
30 * @param appContext
31 * @param usbManager
32 */

33 public static void loadDriver(Context appContext, UsbManager usbManager) {
34 driver = new CH34xUARTDriver(usbManager, appContext, ACTION_USB_PERMISSION);
35 // 判断系统是否支持USB HOST
36 if (!driver.UsbFeatureSupported()) {
37 InLog.e(TAG, "Your mobile phone does not support USB HOST, please change other phones to try again!");
38 } else {
39 openCH340();
40 }
41 }
42 /**
43 * config and open ch340.
44 */

45 private static void openCH340() {
46 int ret_val = driver.ResumeUsbList();
47 InLog.d(TAG, ret_val + "");
48 // ResumeUsbList方法用于枚举CH34X设备以及打开相关设备
49 if (ret_val == -1) {
50 InLog.d(TAG, ret_val + "Failed to open device!");
51 driver.CloseDevice();
52 } else if (ret_val == 0) {
53 if (!driver.UartInit()) { //对串口设备进行初始化操作
54 InLog.d(TAG, ret_val + "Failed device initialization!");
55 InLog.d(TAG, ret_val + "Failed to open device!");
56 return;
57 }
58 InLog.d(TAG, ret_val + "Open device successfully!");
59 if (!isOpenDeviceCH340) {
60 isOpenDeviceCH340 = true;
61 configParameters();//配置ch340的参数、需要先配置参数
62 }
63 } else {
64 InLog.d(TAG, "The phone couldn't find the device!");
65 }
66 }
67 /**
68 * config ch340 parameters.
69 * 配置串口波特率,函数说明可参照编程手册
70 */

71 private static void configParameters() {
72 if (driver.SetConfig(baudRate, dataBit, stopBit, parity, flowControl)) {
73 InLog.d(TAG, "Successful serial port Settings!");
74 if (readDataRunnable == null) {
75 readDataRunnable = new ReadDataRunnable();
76 }
77 mThreadPool.execute(readDataRunnable);
78 } else {
79 InLog.d(TAG, "Serial port Settings failed!");
80 }
81 }

3.2发送和接收数据

发送和接收数据都是按16进制进行发送和处理的,所以我们写了一个工具类方便发送,如下:

 1/**
2 * Created by xpf on 2018/2/6 :)
3 * Function:CH340数据处理工具类
4 */

5public class CH340Util {
6 /**
7 * write data in ch340.
8 *
9 * @param byteArray 字节数组
10 * @return 返回写入的结果,-1表示写入失败!
11 */

12 public static int writeData(@NonNull byte[] byteArray) {
13 // 将此处收到的数组转化为HexString
14 String hexString = bytesToHexString(byteArray, byteArray.length);
15 InLog.i("TAG", "WriteHexString===" + hexString);
16 return InitCH340.getDriver().WriteData(byteArray, byteArray.length);
17 }
18 /**
19 * byte[]转换为hexString
20 *
21 * @param buffer 数据
22 * @param size 字符数
23 * @return 返回转换后的十六进制字符串
24 */

25 public static String bytesToHexString(byte[] buffer, final int size) {
26 StringBuilder stringBuilder = new StringBuilder("");
27 if (buffer == null || size <= 0) return null;
28 for (int i = 0; i < size; i++) {
29 String hex = Integer.toHexString(buffer[i] & 0xff);
30 if (hex.length() < 2) stringBuilder.append(0);
31 stringBuilder.append(hex);
32 }
33 return stringBuilder.toString();
34 }
35}

然后基本的发送和接收数据就写完了,发送数据时调用 writeData() 方法就可以了,接收数据也类似,具体的业务及通讯的协议、加密规则等都需要你和硬件提供方进行协商对接制定,由于涉及到公司机密,此处我就不进行说明了,只说一下最基本的发送和接收数据。

4.插入模块实现自动打开APP

Android中USB的插拔都会发送一个广播,我们只需要在AndroidMenifest.xml文件中接收这个广播就可以了,当我们入模块的时候就会启动我们的APP,第一次会弹出一个对话框询问我们是否打开xxx应用,我们点击确认即可,另外不是我们插入任何USB设备都打开我们的应用,所以我们需要过滤掉对我们没有用的设备,在res下建一个xml目录,新建usb_filter.xml文件,配置好我们这个USB设备模块的product-id和vendor-id,每个模块厂家这个值都是不一样的,有两种获取方式,一个是代码中枚举USB设备然后打印出来,另外一种方法是打开Logcat观察,然后插入USB设备,你会发现系统会打印出来这个USB设备等信息。

最后不要忘了添加权限:

1    <uses-feature
2 android:name="android.hardware.usb.host"
3 android:required="true" />

4 <uses-permission android:name="android.hardware.usb.host" />

此处由于篇幅原因就不具体展开讲解更多细节了,核心的代码和实现我都已经贴出来了,要想查看更具体的实现,请下载我的demo:

https://github.com/xinpengfei520/USB-OTG-CH340-UART-interface

若在阅读过程中遇到什么问题,或有好提议,欢迎在公众号“CodingAndroid”中提出

长按后点击扫一扫关注!长按后点击扫一扫关注!

转载于:https://www.cnblogs.com/angel88/p/8684899.html

相关文章:

  • 扑克千术
  • 删除数据库中所有表
  • 初来乍到
  • .NET成年了,然后呢?
  • android 线程消息深入
  • ios动态库和静态库
  • Chrome开发——第一个博客链接插件
  • RabbitMQ消息队列(九):Publisher的消息确认机制
  • 减治算法求n个数中的最小数的位置
  • spark2.1.0 自定义AccumulatorV2累加少值(线程不安全)?
  • heartbeat+ldirectord实现web与dns的高可用性
  • __new__ 是什么鬼
  • C#面向对象20 序列化和反序列化
  • SecureCRT 只用 RZ 命令上传大文件失败
  • Ubuntu 10.04下安装libgtk2.0-dev
  • [case10]使用RSQL实现端到端的动态查询
  • 2019年如何成为全栈工程师?
  • Android框架之Volley
  • Docker入门(二) - Dockerfile
  • Electron入门介绍
  • idea + plantuml 画流程图
  • Javascripit类型转换比较那点事儿,双等号(==)
  • Laravel Mix运行时关于es2015报错解决方案
  • 阿里云爬虫风险管理产品商业化,为云端流量保驾护航
  • 爱情 北京女病人
  • 程序员该如何有效的找工作?
  • 对JS继承的一点思考
  • 分享一份非常强势的Android面试题
  • 开年巨制!千人千面回放技术让你“看到”Flutter用户侧问题
  • 聊聊spring cloud的LoadBalancerAutoConfiguration
  • 前端 CSS : 5# 纯 CSS 实现24小时超市
  • 区块链将重新定义世界
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 设计模式走一遍---观察者模式
  • 实现简单的正则表达式引擎
  • 项目实战-Api的解决方案
  • 找一份好的前端工作,起点很重要
  • 中文输入法与React文本输入框的问题与解决方案
  • ​sqlite3 --- SQLite 数据库 DB-API 2.0 接口模块​
  • #经典论文 异质山坡的物理模型 2 有效导水率
  • #我与Java虚拟机的故事#连载04:一本让自己没面子的书
  • $jQuery 重写Alert样式方法
  • (android 地图实战开发)3 在地图上显示当前位置和自定义银行位置
  • (C++20) consteval立即函数
  • (libusb) usb口自动刷新
  • (Redis使用系列) Springboot 实现Redis消息的订阅与分布 四
  • (第二周)效能测试
  • (附源码)spring boot网络空间安全实验教学示范中心网站 毕业设计 111454
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (附源码)springboot优课在线教学系统 毕业设计 081251
  • (附源码)ssm户外用品商城 毕业设计 112346
  • (附源码)ssm经济信息门户网站 毕业设计 141634
  • (机器学习-深度学习快速入门)第三章机器学习-第二节:机器学习模型之线性回归
  • (十二)devops持续集成开发——jenkins的全局工具配置之sonar qube环境安装及配置
  • (四)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)