阳光沙滩
让学习编程变得简单
Android——USB转COM口(CH340)与传感器进行通讯
发表于 2020-03-16    阅读次数 885

本人使用环境

  • CH340转接头
  • Android5.1,RK3188
  • Android6.0,RK3288

关于CH34官方的jar包与使用存在的问题(官方地址)

  • 最大的问题是无法修改串口波特率,一直以19200运行,但我的传感器为9600,理论上应该可以修改,可是就连官方的APK都无法修改,我只好另寻他发

最终解决方案

初始化

  • 在你的build.gradle(project)中添加
allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}
  • 添加依赖
dependencies {
    implementation 'com.github.mik3y:usb-serial-for-android:2.2.2'
}
  • 添加权限
<uses-feature android:name="android.hardware.usb.host" />
  • res/xml/下添加 device_filter.xml,CH340官网的工程Demo内也有。并要在AndroidManifest中补全代码
<resource>
   <usb-device product-id="29987" vendor-id="6790" />
   <usb-device product-id="21795" vendor-id="6790" />
   <usb-device product-id="21778" vendor-id="6790" />
</resource>
<activity
    android:name="..."
    ...>
    <intent-filter>
        <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
    </intent-filter>
    <meta-data
        android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
        android:resource="@xml/device_filter" />
</activity>

使用

  • 创建单独的温度传感器类
class TemperMoudle {
    private final static String TAG = "MainActivity";

    private static final int TEMPERATURE_USB_VENDOR_ID  = 6790;     //供应商id
    private static final int TEMPERATURE_USB_PRODUCT_ID = 29987;    //产品id

    private Context context;

    private List<UsbSerialDriver> usbSerialDrivers   = null;
    private List<UsbSerialPort>   usbSerialPorts     = new ArrayList<>();
    private UsbSerialPort         temperatureUsbPort = null;

    private SerialInputOutputManager          serialIoManager;
    private SerialInputOutputManager.Listener serialListener;
    private ExecutorService                   executor = Executors.newSingleThreadExecutor();

    TemperMoudle(Context context) {
        this.context = context;
    }

    /**
     * 初始化,获取目标端口
     */
    UsbSerialPort init(SerialInputOutputManager.Listener listener) {
        this.serialListener = listener;
        //获取全部设备
        UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
        if (usbManager != null) {
            usbSerialDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(usbManager);
        }
        //获取全部端口
        if (usbSerialDrivers != null) {
            for (UsbSerialDriver driver : usbSerialDrivers) {
                usbSerialPorts.addAll(driver.getPorts());
            }
        }
        //校验端口设备,获得目标端口
        for (UsbSerialPort port : usbSerialPorts) {
            UsbDevice device = port.getDriver().getDevice();
            if (device.getVendorId() == TEMPERATURE_USB_VENDOR_ID && device.getProductId() == TEMPERATURE_USB_PRODUCT_ID) {
                UsbDeviceConnection connection = usbManager.openDevice(device);
                try {
                    temperatureUsbPort = port;
                    temperatureUsbPort.open(connection);
                    temperatureUsbPort.setParameters(9600, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);
                    //我这里需要开启RTS,否则无法读取数据,但务必记得在temperatureUsbPort.close之前置位false,否则再次启动程序无法读取端口!
                    temperatureUsbPort.setRTS(true);
                } catch (IOException e) {
                    Log.e(TAG, "打开端口失败");
                    try {
                        temperatureUsbPort.setRTS(false);
                        temperatureUsbPort.close();
                    } catch (IOException e2) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return temperatureUsbPort;
    }

    /**
     * 设置数据监听器
     *
     * @param listener 监听器
     */
    void setSerialListener(SerialInputOutputManager.Listener listener) {
        this.serialListener = listener;
    }

    private void startIoManager() {
        if (temperatureUsbPort != null) {
            serialIoManager = new SerialInputOutputManager(temperatureUsbPort, serialListener);
            executor.submit(serialIoManager);
        }
    }

    private void stopIoManager() {
        if (serialIoManager != null) {
            serialIoManager.stop();
            serialIoManager = null;
        }
    }

    /**
     * 重新开启USB管理器
     */
    void onDeviceStateChange() {
        stopIoManager();
        startIoManager();
    }

    void onPause() {
        stopIoManager();
        if (temperatureUsbPort != null) {
            try {
                temperatureUsbPort.setRTS(false);
                temperatureUsbPort.close();
                temperatureUsbPort = null;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
  • 主函数使用
TemperMoudle  temperMoudle;
UsbSerialPort temperUsbPort;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //获取温度传感器数据端口
    temperMoudle = new TemperMoudle(this);
    temperUsbPort = temperMoudle.init(temperListener);

    //发送查询温度的指令
    if (temperUsbPort != null) {
        try {
            temperUsbPort.write(Str16ToBytes("01 03 00 00 00 01 84 0A", " "), 200);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

/**
 * 监听USB端口数据
 */
SerialInputOutputManager.Listener temperListener = new SerialInputOutputManager.Listener() {
    @Override
    public void onNewData(byte[] data) {
        String[] dataStrings = BytesToStrs16(data);
        for (String dataString : dataStrings) {
            Log.d(TAG, "dataString: " + dataString);
        }
    }

    @Override
    public void onRunError(Exception e) {
        e.printStackTrace();
    }
};

/**
 * 用于检测usb插入状态的BroadcasReceiver
 */
private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
    public void onReceive(Context context, Intent intent) {
        if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(intent.getAction())) {
            Log.e(TAG, "设备移除");
            temperMoudle.onPause();
            finish();
        }
    }
};

@Override
protected void onResume() {
    super.onResume();
    IntentFilter usbFilter = new IntentFilter();
    usbFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
    registerReceiver(usbReceiver, usbFilter);
    temperMoudle.onDeviceStateChange();
}

@Override
protected void onPause() {
    super.onPause();
    temperMoudle.onPause();
    unregisterReceiver(usbReceiver);
}

/**
 * 16进制字符串转byte数组
 *
 * @param str        需要转换的字符串
 * @param splitChare 中断间隔符
 * @return 转换好的byte[]数组
 */
public byte[] Str16ToBytes(String str, String splitChare) {
    String[] string = str.trim().split(splitChare);
    byte[] bytes = new byte[string.length];
    for (int i = 0; i < string.length; i++) {
        bytes[i] = (byte) (Integer.parseInt(string[i], 16) & 0xff);
    }
    return bytes;
}

/**
 * 十进制bytes转16进制strings
 *
 * @param bytes 十进制bytes
 * @return 16进制strings
 */
public String[] BytesToStrs16(byte[] bytes) {
    String[] strs = new String[bytes.length];
    for (int i = 0; i < bytes.length; i++) {
        strs[i] = Integer.toHexString(bytes[i] & 0xff);
    }
    return strs;
}