Android USB串口通信问题:仅回显发送的数据
USB串口通信收到回发数据的问题排查与修复
问题描述
使用usb-serial-for-android库与USB设备通信,能够检测设备、打开端口并发送数据,但接收的数据始终是刚发送的内容。
代码中的关键问题点
1. 权限请求的死循环错误
代码中用while (!manager.hasPermission(device)) { manager.requestPermission(device, pendingIntent); }的死循环请求权限,这是错误的:
requestPermission是异步操作,不会立刻返回权限结果,死循环会导致CPU占用过高,甚至应用无响应。- 正确做法是通过广播接收器接收权限申请结果,而非同步等待。
2. 主线程执行耗时操作
直接在主线程调用Thread.sleep(1000)以及串口打开、数据发送等操作,会触发应用无响应(ANR),所有硬件交互必须放在子线程中执行。
3. 发送冗余空字节
request数组以端口最大包大小初始化,但仅填充前6个有效字节,发送时会将整个数组(含大量空字节)发给设备,可能导致设备无法正常响应,甚至触发硬件回环。
4. 串口参数匹配问题
需确认设备实际的串口参数(波特率、停止位、奇偶校验)是否与代码中port.setParameters(1200, 8, UsbSerialPort.STOPBITS_2, UsbSerialPort.PARITY_NONE)完全一致,参数不匹配会导致通信异常。
修复方案
步骤1:替换权限请求逻辑,使用广播接收器
private static final String ACTION_USB_PERMISSION = "com.your.package.USB_PERMISSION"; private BroadcastReceiver usbPermissionReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 注册权限广播接收器 usbPermissionReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (ACTION_USB_PERMISSION.equals(action)) { synchronized (this) { UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { if (device != null) { // 权限获取成功,在子线程处理设备连接 new Thread(() -> connectToDevice(device)).start(); } } else { runOnUiThread(() -> Toast.makeText(context, "USB权限被拒绝", Toast.LENGTH_SHORT).show()); } } } } }; IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION); registerReceiver(usbPermissionReceiver, filter); // 初始化设备检测 initUsbDeviceDetection(); } private void initUsbDeviceDetection() { UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE); UsbSerialProber usbDefaultProber = UsbSerialProber.getDefaultProber(); HashMap<String, UsbDevice> deviceList = manager.getDeviceList(); if (deviceList.isEmpty()) { runOnUiThread(() -> { Toast.makeText(this, "未检测到USB设备", Toast.LENGTH_LONG).show(); infos.setText("未检测到USB设备"); }); spinner.setVisibility(View.GONE); return; } for (UsbDevice device : deviceList.values()) { runOnUiThread(() -> { Toast.makeText(this, "检测到设备:" + device.getProductName(), Toast.LENGTH_LONG).show(); Toast.makeText(this, "设备信息:VendorId=" + device.getVendorId() + " ProductId=" + device.getProductId(), Toast.LENGTH_LONG).show(); }); UsbSerialDriver driver = usbDefaultProber.probeDevice(device); if (driver == null) { ProbeTable customTable = new ProbeTable(); customTable.addProduct(device.getVendorId(), device.getProductId(), Cp21xxSerialDriver.class); UsbSerialProber customProber = new UsbSerialProber(customTable); driver = customProber.probeDevice(device); } if (driver != null) { // 请求权限 PendingIntent pendingIntent; if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE); } else { pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), PendingIntent.FLAG_UPDATE_CURRENT); } manager.requestPermission(device, pendingIntent); } else { runOnUiThread(() -> Toast.makeText(this, "无可用驱动", Toast.LENGTH_LONG).show()); spinner.setVisibility(View.GONE); } } }
步骤2:在子线程中处理设备连接与数据发送
private void connectToDevice(UsbDevice device) { UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE); UsbSerialProber usbDefaultProber = UsbSerialProber.getDefaultProber(); UsbSerialDriver driver = usbDefaultProber.probeDevice(device); if (driver == null) { ProbeTable customTable = new ProbeTable(); customTable.addProduct(device.getVendorId(), device.getProductId(), Cp21xxSerialDriver.class); UsbSerialProber customProber = new UsbSerialProber(customTable); driver = customProber.probeDevice(device); } if (driver == null) { runOnUiThread(() -> Toast.makeText(this, "无可用驱动", Toast.LENGTH_LONG).show()); spinner.setVisibility(View.GONE); return; } try { UsbDeviceConnection connection = manager.openDevice(device); if (connection == null) { runOnUiThread(() -> Toast.makeText(this, "无法建立连接", Toast.LENGTH_LONG).show()); spinner.setVisibility(View.GONE); return; } runOnUiThread(() -> { infos.setText("发送数据中..."); Toast.makeText(this, "发送数据中...", Toast.LENGTH_LONG).show(); }); UsbSerialPort port = driver.getPorts().get(0); port.open(connection); // 确认设备实际参数与这里一致 port.setParameters(1200, 8, UsbSerialPort.STOPBITS_2, UsbSerialPort.PARITY_NONE); // 初始化仅包含有效数据的数组 byte[] request = new byte[6]; request[0] = hexIntToByte(0x80); request[1] = hexIntToByte(0x3F); request[2] = hexIntToByte(0x01); request[3] = hexIntToByte(0x05); // CRC MSByte request[4] = hexIntToByte(0x8A); // CRC LSByte request[5] = hexIntToByte(0x0D); // Stop Byte // 启动串口IO管理器 SerialInputOutputManager usbIoManager = new SerialInputOutputManager(port, this); usbIoManager.start(); // 发送数据(仅发送有效字节) port.write(request, 0); runOnUiThread(() -> { String infosText = "信息\n"; infosText += "发送的数据 = " + byteArrayToHexString(request) + "\n"; infos.setText(infosText); }); } catch (Exception e) { String erreur = e.toString(); runOnUiThread(() -> { Toast.makeText(this, "错误:" + erreur, Toast.LENGTH_LONG).show(); String erreurText = "错误\n"; erreurText += "发送的数据 = " + byteArrayToHexString(request) + "\n"; erreurText += "错误信息 = " + erreur + "\n"; infos.setText(erreurText); }); } finally { runOnUiThread(() -> spinner.setVisibility(View.GONE)); } }
步骤3:检查硬件连接
如果修复后仍收到回发数据,需确认设备的TX与RX引脚是否被短接(硬件回环),这会导致发送的数据被直接回传到接收端。
数据接收方法保持不变
@Override public void onNewData(byte[] data) { runOnUiThread(() -> infos.append(byteArrayToHexString(data))); }
内容的提问来源于stack exchange,提问作者erbl
相关产品推荐
相关产品推荐

