Android Serial串口开发全流程指南:从基础到实战

作者:谁偷走了我的奶酪2025.10.23 21:27浏览量:76

简介:本文详细解析Android设备串口通信的实现方法,涵盖权限配置、硬件连接、驱动适配及代码实现,提供可落地的开发方案与调试技巧。

一、Android串口通信基础与适用场景

1.1 串口通信技术原理

串口通信(Serial Communication)通过数据线按位传输数据,采用异步通信协议(如RS-232、RS-485)。Android设备通过USB转串口芯片(如CH340、FT232)或内置串口控制器实现物理层连接,数据传输速率通常为9600-115200bps。

1.2 Android串口应用场景

  • 工业设备控制(PLC、传感器)
  • 医疗设备数据采集(心电图机、血氧仪)
  • 智能家居系统(温湿度传感器、红外控制器)
  • 车载诊断系统(OBD-II接口)

1.3 开发前准备

  • 硬件:USB转串口适配器(需支持Android OTG)、串口设备
  • 软件:Android Studio 4.0+、USB驱动(如FTDI的D2XX驱动)
  • 权限:android.permission.USB_PERMISSIONWRITE_EXTERNAL_STORAGE

二、Android串口开发核心步骤

2.1 权限配置与设备检测

AndroidManifest.xml中添加权限:

  1. <uses-permission android:name="android.permission.USB_PERMISSION" />
  2. <uses-feature android:name="android.hardware.usb.host" />

通过UsbManager检测已连接设备:

  1. UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
  2. HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
  3. for (UsbDevice device : deviceList.values()) {
  4. if (isSerialDevice(device)) { // 自定义设备识别逻辑
  5. PendingIntent permissionIntent = PendingIntent.getBroadcast(
  6. this, 0, new Intent(ACTION_USB_PERMISSION), 0);
  7. usbManager.requestPermission(device, permissionIntent);
  8. }
  9. }

2.2 串口驱动适配方案

方案一:使用Android USB Host API(需内核支持)

  1. UsbDeviceConnection connection = usbManager.openDevice(device);
  2. UsbInterface usbInterface = device.getInterface(0);
  3. UsbEndpoint endpointIn = usbInterface.getEndpoint(0);
  4. UsbEndpoint endpointOut = usbInterface.getEndpoint(1);
  5. // 配置串口参数(波特率、数据位等需通过控制传输实现)
  6. byte[] request = new byte[]{(byte) 0x80, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00};
  7. connection.controlTransfer(0x40, 0x03, 0x0000, 0x0000, request, 7, 5000);

方案二:集成第三方库(推荐)

  • UsbSerial:支持CH340/CP2102/FTDI等常见芯片
    1. implementation 'com.github.mik3y:usb-serial-for-android:3.4.3'
    示例代码:
    1. UsbSerialDriver driver = UsbSerialProber.getDefaultProber().probeDevice(device);
    2. UsbSerialPort port = driver.getPorts().get(0);
    3. port.open(connection);
    4. port.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);

2.3 数据收发实现

2.3.1 异步接收机制

  1. private final Handler mHandler = new Handler(Looper.getMainLooper()) {
  2. @Override
  3. public void handleMessage(Message msg) {
  4. byte[] buffer = (byte[]) msg.obj;
  5. // 处理接收到的数据
  6. }
  7. };
  8. private void startReading(UsbSerialPort port) {
  9. new Thread(() -> {
  10. byte[] buffer = new byte[1024];
  11. while (isRunning) {
  12. int size = port.read(buffer, 1000);
  13. if (size > 0) {
  14. Message msg = mHandler.obtainMessage();
  15. msg.obj = Arrays.copyOf(buffer, size);
  16. mHandler.sendMessage(msg);
  17. }
  18. }
  19. }).start();
  20. }

2.3.2 发送数据封装

  1. public boolean sendData(byte[] data) {
  2. try {
  3. int offset = 0;
  4. while (offset < data.length) {
  5. int bytesWritten = port.write(data, offset, data.length - offset);
  6. if (bytesWritten <= 0) {
  7. return false;
  8. }
  9. offset += bytesWritten;
  10. }
  11. return true;
  12. } catch (IOException e) {
  13. e.printStackTrace();
  14. return false;
  15. }
  16. }

三、常见问题与解决方案

3.1 权限拒绝问题

  • 现象SecurityException: User 10153 does not have android.permission.USB_PERMISSION
  • 解决
    1. 动态请求权限时确保PendingIntent正确配置
    2. 在设备管理器中手动授权(适用于调试阶段)

3.2 驱动兼容性问题

  • CH340芯片识别失败
    1. // 自定义Prober示例
    2. public class Ch340Prober extends UsbSerialProber {
    3. @Override
    4. protected UsbSerialDriver getDriver(UsbDevice device) {
    5. if (device.getVendorId() == 0x1A86 && device.getProductId() == 0x7523) {
    6. return new Ch340Driver(device);
    7. }
    8. return null;
    9. }
    10. }

3.3 数据粘包处理

  • 解决方案
    1. 固定长度协议:每次发送固定字节数
    2. 分隔符协议:使用\n或特定字符作为帧结束符
    3. 协议头标识:包含数据长度字段

四、性能优化建议

4.1 缓冲区管理

  • 采用双缓冲机制减少线程阻塞
    1. private final BlockingQueue<byte[]> sendQueue = new LinkedBlockingQueue<>(16);
    2. private final BlockingQueue<byte[]> receiveQueue = new LinkedBlockingQueue<>(32);

4.2 波特率适配

  • 根据设备能力动态选择最优波特率:
    1. public static int getOptimalBaudRate(UsbDevice device) {
    2. if (device.getVendorId() == 0x0403 && device.getProductId() == 0x6001) {
    3. return 921600; // FTDI芯片支持高速率
    4. }
    5. return 115200; // 默认安全速率
    6. }

4.3 功耗优化

  • 非活跃状态关闭串口:
    1. @Override
    2. protected void onPause() {
    3. super.onPause();
    4. if (port != null && port.isOpen()) {
    5. port.close();
    6. }
    7. }

五、完整项目结构示例

  1. app/
  2. ├── src/
  3. ├── main/
  4. ├── java/com/example/serial/
  5. ├── SerialManager.java # 串口核心逻辑
  6. ├── DeviceDetector.java # 设备检测
  7. └── ProtocolParser.java # 数据解析
  8. └── res/
  9. └── xml/device_filter.xml # USB设备过滤配置
  10. └── AndroidManifest.xml
  11. └── build.gradle

device_filter.xml示例:

  1. <resources>
  2. <usb-device vendor-id="1027" product-id="24597" /> <!-- FTDI示例 -->
  3. <usb-device class="255" subclass="0" protocol="0" /> <!-- 自定义类设备 -->
  4. </resources>

六、进阶功能实现

6.1 多串口管理

  1. public class MultiSerialManager {
  2. private final SparseArray<UsbSerialPort> ports = new SparseArray<>();
  3. public void addPort(int portId, UsbSerialPort port) {
  4. ports.put(portId, port);
  5. }
  6. public boolean broadcast(byte[] data) {
  7. boolean success = true;
  8. for (int i = 0; i < ports.size(); i++) {
  9. if (!sendData(ports.valueAt(i), data)) {
  10. success = false;
  11. }
  12. }
  13. return success;
  14. }
  15. }

6.2 协议栈集成

  • 实现Modbus RTU协议示例:

    1. public class ModbusRtu {
    2. public static byte[] readHoldingRegisters(int slaveId, int startAddr, int quantity) {
    3. byte[] frame = new byte[8];
    4. frame[0] = (byte) slaveId;
    5. frame[1] = 0x03; // 功能码
    6. frame[2] = (byte) (startAddr >> 8);
    7. frame[3] = (byte) startAddr;
    8. frame[4] = (byte) (quantity >> 8);
    9. frame[5] = (byte) quantity;
    10. // 计算CRC
    11. int crc = calculateCRC(frame, 6);
    12. frame[6] = (byte) (crc & 0xFF);
    13. frame[7] = (byte) (crc >> 8);
    14. return frame;
    15. }
    16. }

本教程系统覆盖了Android串口开发的全流程,从基础权限配置到高级协议实现均提供了可落地的解决方案。实际开发中建议结合具体硬件特性进行适配,并通过日志系统(如Timber)完善调试信息。对于商业项目,建议采用模块化设计,将串口通信层与业务逻辑解耦,提高代码可维护性。