使用jSerialComm结合CP210驱动实现串口通信时无法读取数据的问题排查
串口通信读取失败问题排查(JavaFX + jSerialComm + CP210)
以下是你的代码中可能导致无法读取设备返回数据的几个问题:
十六进制转字节数组的写入长度错误:
你调用hexStringToByteArray("CC")后传入writeBytes(hexBytes, 2),但"CC"作为两位十六进制字符串,正确转换后应为1个字节(0xCC)。如果hexStringToByteArray实现正确,写2个字节会导致写入无效数据(比如数组越界或填充0),设备无法识别指令自然不会返回数据。需确认hexStringToByteArray的实现,同时将写入长度改为数组实际长度:byte[] hexBytes = hexStringToByteArray("CC"); _serialPort.writeBytes(hexBytes, hexBytes.length); // 用实际数组长度而非固定值2休眠时间计算错误:
TimeUnit.SECONDS.sleep(1 / 3)中,整数除法结果为0,相当于无休眠。连续快速发送指令会导致设备来不及处理,需改为毫秒级休眠:TimeUnit.MILLISECONDS.sleep(333); // 替代1/3秒的休眠逻辑读取逻辑的不合理之处:
- 直接用
bytesAvailable()的结果创建缓冲区,可能在缓冲区创建到readBytes调用的间隙,设备新返回的数据还未到达,导致读不全; - 将字节数组直接转成
String并trim(),若设备返回二进制数据或非UTF-8编码字符串,会出现乱码或丢失有效数据,建议先打印原始字节数组或十六进制字符串排查:System.out.println("原始返回数据:" + Arrays.toString(readBuffer)); // 转十六进制字符串输出 StringBuilder hexStr = new StringBuilder(); for (byte b : readBuffer) { hexStr.append(String.format("%02X ", b)); } System.out.println("十六进制返回:" + hexStr.toString().trim()); - 仅读取一次可能无法获取完整返回,建议循环读取直到超时或满足终止条件(比如读到特定结束符)。
- 直接用
设备初始化与流控制问题:
- 恢复注释掉的
TimeUnit.SECONDS.sleep(1);,CP210设备打开端口后需要短暂时间完成初始化; - 确认
setDTR()和setRTS()的状态是否符合设备要求,部分设备需要拉低DTR/RTS才能正常通信,可先注释这两行测试; - 增加端口打开成功的判断:
if (!_serialPort.openPort()) { System.err.println("端口打开失败"); return; }
- 恢复注释掉的
修正后的核心代码示例:
SerialPort _serialPort; SerialPort[] ports = SerialPort.getCommPorts(); if (ports.length == 0) { System.err.println("未找到串口设备"); return; } _serialPort = SerialPort.getCommPort(ports[0].getSystemPortName()); System.out.println(ports[0].getSystemPortName()); _serialPort.setBaudRate(19200); _serialPort.setNumDataBits(8); _serialPort.setNumStopBits(1); _serialPort.setParity(SerialPort.NO_PARITY); // 先注释DTR/RTS测试,或根据设备手册调整状态 // _serialPort.setDTR(); // _serialPort.setRTS(); if (!_serialPort.openPort()) { System.err.println("端口打开失败"); return; } _serialPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING, 4000, 4000); TimeUnit.SECONDS.sleep(1); // 恢复初始化休眠 // 发送指令:使用数组实际长度写入 String[] hexCommands = {"CC", "AB", "AB"}; for (String cmd : hexCommands) { byte[] hexBytes = hexStringToByteArray(cmd); _serialPort.writeBytes(hexBytes, hexBytes.length); TimeUnit.MILLISECONDS.sleep(333); } TimeUnit.SECONDS.sleep(1); // 读取数据(使用固定长度缓冲区,避免漏读) byte[] readBuffer = new byte[1024]; long readLen = _serialPort.readBytes(readBuffer, readBuffer.length); if (readLen > 0) { System.out.println("读取字节数:" + readLen); // 打印十六进制数据 StringBuilder hexStr = new StringBuilder(); for (int i = 0; i < readLen; i++) { hexStr.append(String.format("%02X ", readBuffer[i])); } System.out.println("十六进制返回:" + hexStr.toString().trim()); // 转字符串(确认设备编码后使用) String response = new String(readBuffer, 0, (int)readLen).trim(); System.out.println("字符串返回:" + response); if (response.startsWith("BLE_READER")) { String[] ab = response.split(","); System.out.println("yess logger1 "+ Arrays.toString(ab)); welcomeText.setText("读取成功:" + response); } else { _serialPort.closePort(); } } else { System.err.println("未读取到数据"); _serialPort.closePort(); }
内容的提问来源于stack exchange,提问作者Tejas Chauhan
相关产品推荐
相关产品推荐

