Android-usb通信(usb转rs232)

987 阅读2分钟

前言

通过usb可以和外接设备进行数据交互,比如开发板,外设,单片机等。两台android设备如何连接?通过usb转232线,实现消息通讯。

实现方式

相关类

UsbManager
UsbDevice
getSerialNumber() 设备唯一序列号
getDeviceId() 此设备的ID号
getDeviceName() 设备的名称
getVendorId() 生产商ID
getProductId() 产品ID
  • 寻找已连接的设备
ArrayBlockingQueue<PendingUsbPermission> queuedPermissions = new ArrayBlockingQueue<>(100);
UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE)
HashMap<String, UsbDevice> usbDevices = usbManager.getDeviceList();
for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) {
    device = entry.getValue();
    //筛选目标设备
    Timber.d("USBDevice.HashMap (vid:pid) (%X:%X class:%X:%X name:%s",
            device.getVendorId(), device.getProductId(),
            device.getDeviceClass(), device.getDeviceSubclass(),
   // 为找到的设备请求使用权限
   queuedPermissions.add(createUsbPermission(context, new UsbDeviceStatus(device)));
}
launchPermission();
  • 权限请求
/**
 * 统一请求权限
 */
private void launchPermission() {
    try {
        processingPermission = true;
        currentPendingPermission = queuedPermissions.take();
        usbManager.requestPermission(currentPendingPermission.usbDeviceStatus.usbDevice,
                currentPendingPermission.pendingIntent);
    } catch (InterruptedException e) {
        e.printStackTrace();
        processingPermission = false;
    }
}

/**
 * 构建请求意图
 * @param context
 * @param usbDeviceStatus
 * @return
 */
private PendingUsbPermission createUsbPermission(Context context, UsbDeviceStatus usbDeviceStatus) {
    PendingIntent mPendingIntent = PendingIntent.getBroadcast(context, 0,
            new Intent(ACTION_USB_PERMISSION), 0);
    PendingUsbPermission pendingUsbPermission = new PendingUsbPermission();
    pendingUsbPermission.pendingIntent = mPendingIntent;
    pendingUsbPermission.usbDeviceStatus = usbDeviceStatus;
    return pendingUsbPermission;
}

private class UsbDeviceStatus {
    public UsbDevice usbDevice;
    public UsbDeviceConnection usbDeviceConnection;
    public boolean open;
    public UsbDeviceStatus(UsbDevice usbDevice) {
        this.usbDevice = usbDevice;
    }

    @Override
    public boolean equals(Object obj) {
        UsbDeviceStatus usbDeviceStatus = (UsbDeviceStatus) obj;
        return usbDeviceStatus.usbDevice.getDeviceId() == usbDevice.getDeviceId();
    }
}
  • 权限获取后处理
private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context arg0, Intent arg1) {
        if (arg1.getAction().equals(ACTION_USB_PERMISSION)) {
            Timber.e("device ACTION_USB_PERMISSION");
            boolean granted = arg1.getExtras().getBoolean(UsbManager.EXTRA_PERMISSION_GRANTED);
            // User accepted our USB connection. Try to open the device as a serial port
            if (granted) {
                //
                initSerialPort(currentPendingPermission.usbDeviceStatus.usbDevice);
                if (queuedPermissions.size() > 0) {
                    launchPermission();
                } else {
                    processingPermission = false;
                    //通信线程,获取消息,发送消息
                    // callback 自定义消息处理
                    new ConnectionThread(1, port, callback).start();
                }
            }
        } else if (arg1.getAction().equals(ACTION_USB_ATTACHED)) {
           //todo
        } else if (arg1.getAction().equals(ACTION_USB_DETACHED)) {
           //todo
        }
    }
};

  • 连接线程
private class ConnectionThread extends Thread {
    UsbSerialDevice serialPort;
    UsbSerialInterface.UsbReadCallback mCallback;

    public ConnectionThread(int type, UsbSerialDevice inSerial, UsbSerialInterface.UsbReadCallback inCallback) {
        mType = type;
        serialPort = inSerial;
        mCallback = inCallback;
    }

    @Override
    public void run() {
        if (serialPort != null) {
            if (serialPort.open()) {
                // 波特率,起始位,终止位,数据位
                serialPort.setBaudRate(BAUD_RATE);
                serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
                serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
                serialPort.setParity(UsbSerialInterface.PARITY_NONE);
                /**
                 * Current flow control Options:
                 * UsbSerialInterface.FLOW_CONTROL_OFF
                 * UsbSerialInterface.FLOW_CONTROL_RTS_CTS only for CP2102 and FT232
                 * UsbSerialInterface.FLOW_CONTROL_DSR_DTR only for CP2102 and FT232
                 */
                serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
                serialPort.read(mCallback);
                serialPort.getCTS(ctsCallback); //Clear To Send 清除发送
                serialPort.getDSR(dsrCallback); //Data Set Ready 数据准备好
                //
                // Some Arduinos would need some sleep because firmware wait some time to know whether a new sketch is going 
                // to be uploaded or not
                //Thread.sleep(2000); // sleep some. YMMV with different chips.
            } else {
                // Serial port could not be opened, maybe an I/O error or if CDC driver was chosen, it does not really fit
                // todo 自处理
            }
        } else {
            // No driver for given device, even generic CDC driver could not be loaded 自处理
        }
    }
}

总结:

  • 依赖库可作为jar包引入
  • usb的通信不限于232,只是举例使用,可用于任意usb通信
  • 本文列举所有关键类的使用