前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >ANDROID OTG USB通信 读写 信息

ANDROID OTG USB通信 读写 信息

作者头像
zhangjiqun
发布2024-12-16 16:55:25
发布2024-12-16 16:55:25
16100
代码可运行
举报
文章被收录于专栏:计算机工具计算机工具
运行总次数:0
代码可运行

github:https://github.com/mik3y/usb-serial-for-android

第一步:获取所有的已插入的串口驱动

代码语言:javascript
代码运行次数:0
复制
1 UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
2 List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager);
3 if (availableDrivers.isEmpty()) {
4   return;
5 }

然后,我们选择第一个dirver ,连接设备

代码语言:javascript
代码运行次数:0
复制
1 UsbSerialDriver driver = availableDrivers.get(0);
2 UsbDeviceConnection connection = manager.openDevice(driver.getDevice());
3 if (connection == null) {
4   // You probably need to call UsbManager.requestPermission(driver.getDevice(), ..)
5   return;
6 }

接下来就可以读数据了

代码语言:javascript
代码运行次数:0
复制
 1 // Read some data! Most have just one port (port 0).
 2 UsbSerialPort port = driver.getPorts().get(0);
 3 try {
 4   port.open(connection);
 5 //设置串口的波特率、数据位,停止位,校验位
 6   port.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);
 7 
 8   byte buffer[] = new byte[16];
 9   int numBytesRead = port.read(buffer, 1000);
10   Log.d(TAG, "Read " + numBytesRead + " bytes.");
11 } catch (IOException e) {
12   // Deal with error.
13 } finally {
14   port.close();
15 }

当然,我们可以给串口添加个监听

代码语言:javascript
代码运行次数:0
复制
 1  1 private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
 2  2 private SerialInputOutputManager mSerialIoManager;
 3  3 
 4  4 private final SerialInputOutputManager.Listener mListener =
 5  5             new SerialInputOutputManager.Listener() {
 6  6                 @Override
 7  7                 public void onRunError(Exception e) {
 8  8                     Log.d(TAG, "Runner stopped.");
 9  9                 }
10 10 
11 11                 @Override
12 12                 public void onNewData(final byte[] data) {
13 13                    //TODO 新的数据
14 14                 }
15 15             };
16 16 
17 17 mSerialIoManager = new SerialInputOutputManager(sPort, mListener);//添加监听
18 //在新的线程中监听串口的数据变化
19 18 mExecutor.submit(mSerialIoManager);

如果需要接受比较大的数据,有可能会遇到一个问题:数据缓存和接收时间不够,导致数据被覆盖或者丢失,我们就需要修改串口读取缓存了

把 SerialInputOutputManager 中的 READ_WAIT_MILLIS 和 BUFSIZ 改成合适的大小就可以了

写数据的操作就是调用port的方法

代码语言:javascript
代码运行次数:0
复制
port.write(bytes, 1000);

其实这个开源项目已经为我们封装了很多驱动类,都在driver包下,我们直接拿来用就可以了

零 USB背景知识

USB是一种数据通信方式,也是一种数据总线,而且是最复杂的总线之一。 硬件上,它是用插头连接。一边是公头(plug),一边是母头(receptacle)。例如,PC上的插座就是母头,USB设备使用公头与PC连接。 目前USB硬件接口分三种,普通PC上使用的叫Type;原来诺基亚功能机时代的接口为Mini USB;目前Android手机使用的Micro USB。

Host USB是由Host端控制整个总线的数据传输的。单个USB总线上,只能有一个Host。 OTG On The Go,这是在USB2.0引入的一种mode,提出了一个新的概念叫主机协商协议(Host Negotiation Protocol),允许两个设备间商量谁去当Host。

一、Android中的USB

Android对Usb的支持是从3.1开始的,显然是加强Android平板的对外扩展能力。而对Usb使用更多的,是Android在工业中的使用。Android工业板子一般都会提供多个U口和多个串口,它们是连接外设的手段与桥梁。下面就来介绍一下Android Usb使用模式之一的USB Host。

android.hardware.usb包下提供了USB开发的相关类。 我们需要了解UsbManager、UsbDevice、UsbInterface、UsbEndpoint、UsbDeviceConnection、UsbRequest、UsbConstants。 1、UsbManager:获得Usb的状态,与连接的Usb设备通信。 2、UsbDevice:Usb设备的抽象,它包含一个或多个UsbInterface,而每个UsbInterface包含多个UsbEndpoint。Host与其通信,先打开UsbDeviceConnection,使用UsbRequest在一个端点(endpoint)发送和接收数据。 3、UsbInterface:定义了设备的功能集,一个UsbDevice包含多个UsbInterface,每个Interface都是独立的。 4、UsbEndpoint:endpoint是interface的通信通道。 5、UsbDeviceConnection:host与device建立的连接,并在endpoint传输数据。 6、UsbRequest:usb 请求包。可以在UsbDeviceConnection上同步异步传输数据。 7、UsbConstants:usb常量的定义,对应linux/usb/ch9.h

二、USB插入事件

Usb的插入和拔出是以系统广播的形式发送的,只要我们注册这个广播即可。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

@Override protected void onResume() { super.onResume(); IntentFilter usbFilter = new IntentFilter(); usbFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); usbFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); registerReceiver(mUsbReceiver, usbFilter); } @Override protected void onPause() { super.onPause(); unregisterReceiver(mUsbReceiver); } private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); tvInfo.append("BroadcastReceiver in\n"); if(UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) { tvInfo.append("ACTION_USB_DEVICE_ATTACHED\n"); } else if(UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) { tvInfo.append("ACTION_USB_DEVICE_DETACHED\n"); } } };

三、Usb插入时启动程序

有些应用场景是,Usb插入后启动特定程序处理特定问题。 我们的做法就是在Manifest中某个Activity加入Usb插入的action。

1 2 3 4

<intent-filter> <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"> </action></intent-filter> <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" android:resource="@xml/usbfilter"></meta-data>

在usbfilter中加入厂商id和产品id的过滤,如下:

1 2 3 4

<resources> <usb-device vendor-id="1234" product-id="5678"> </usb-device></resources>

结果就是,当此型号设备通过Usb连接到系统时,对应的Activity就会启动。

四、UsbManager的初始化

1

mUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE);

五、列出Usb设备

1 2 3 4 5 6 7 8

HashMap<string,usbdevice> deviceHashMap = mUsbManager.getDeviceList(); Iterator<usbdevice> iterator = deviceHashMap.values().iterator(); while (iterator.hasNext()) { UsbDevice device = iterator.next(); tvInfo.append("\ndevice name: "+device.getDeviceName()+"\ndevice product name:" +device.getProductName()+"\nvendor id:"+device.getVendorId()+ "\ndevice serial: "+device.getSerialNumber()); }</usbdevice></string,usbdevice>

六、USB使用权限

安卓系统对USB口的使用需要得到相应的权限,而这个权限要用户亲自给才行。 首先我们会确认一下上一节中的device是否已经获得权限,如果没有就要主动申请权限:

1 2 3 4 5 6 7 8 9 10 11

//先判断是否为自己的设备 //注意:支持十进制和十六进制 //比如:device.getProductId() == 0x04D2 if(device.getProductId() == 1234 && device.getVendorId() == 5678) { if(mUsbManager.hasPermission(device)) { //do your work } else { mUsbManager.requestPermission(device,mPermissionIntent); } }

我们仍然使用广播来获得权限赋予情况。

1public static final String ACTION_DEVICE_PERMISSION = "com.linc.USB_PERMISSION";

注册广播

1 2 3

mPermissionIntent = PendingIntent.getBroadcast(this,0,new Intent(ACTION_DEVICE_PERMISSION),0); IntentFilter permissionFilter = new IntentFilter(ACTION_DEVICE_PERMISSION); registerReceiver(mUsbReceiver,permissionFilter);

接收器的代码:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); tvInfo.append("BroadcastReceiver in\n"); if (ACTION_DEVICE_PERMISSION.equals(action)) { synchronized (this) { UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { if (device != null) { tvInfo.append("usb EXTRA_PERMISSION_GRANTED"); } } else { tvInfo.append("usb EXTRA_PERMISSION_GRANTED null!!!"); } } } } };

七、通信

UsbDevice有了权限,下面就可以进行通信了。 这里要用到:UsbInterface、UsbEndpoint(一进一出两个endpoint,双向通信)、UsbDeviceConnection。 注意:通信的过程不能在UI线程中进行。 得到授权后,将做一些通信前的准备工作,如下:

?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38

private void initCommunication(UsbDevice device) { tvInfo.append("initCommunication in\n"); if(1234 == device.getVendorId() && 5678 == device.getProductId()) { tvInfo.append("initCommunication in right device\n"); int interfaceCount = device.getInterfaceCount(); for (int interfaceIndex = 0; interfaceIndex < interfaceCount; interfaceIndex++) { UsbInterface usbInterface = device.getInterface(interfaceIndex); if ((UsbConstants.USB_CLASS_CDC_DATA != usbInterface.getInterfaceClass()) && (UsbConstants.USB_CLASS_COMM != usbInterface.getInterfaceClass())) { continue; } for (int i = 0; i < usbInterface.getEndpointCount(); i++) { UsbEndpoint ep = usbInterface.getEndpoint(i); if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) { if (ep.getDirection() == UsbConstants.USB_DIR_OUT) { mUsbEndpointIn = ep; } else { mUsbEndpointOut = ep; } } } if ((null == mUsbEndpointIn) || (null == mUsbEndpointOut)) { tvInfo.append("endpoint is null\n"); mUsbEndpointIn = null; mUsbEndpointOut = null; mUsbInterface = null; } else { tvInfo.append("\nendpoint out: " + mUsbEndpointOut + ",endpoint in: " + mUsbEndpointIn.getAddress()+"\n"); mUsbInterface = usbInterface; mUsbDeviceConnection = mUsbManager.openDevice(device); break; } } } }

发送数据如下:

?

1

result = mUsbDeviceConnection.bulkTransfer(mUsbEndpointOut, mData, (int)buffSize, 1500);//需要在另一个线程中进行

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-12-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 零 USB背景知识
  • 一、Android中的USB
  • 二、USB插入事件
  • 三、Usb插入时启动程序
  • 四、UsbManager的初始化
  • 五、列出Usb设备
  • 六、USB使用权限
  • 七、通信
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档