串口传输数据持续缓冲,Android设备无法识别该数据
串口数据缓冲&NFC写入失败问题排查与修复
一、串口数据持续缓冲的核心原因及修复
1. 终止符逻辑缺陷
当前代码依赖"terminator"字符串判断传输结束,但如果串口发送端未发送该标记,或数据中该字符串未完整传输,循环会一直等待,导致数据滞留在缓冲。
2. 字符串拼接的编码隐患
dataFromSerial += new String(buffer, 0, bytesRead)直接用默认编码拼接,若串口数据含多字节字符会出现乱码,进而导致终止符检测失效。
3. 超时逻辑未合理利用
serialPort.read(buffer, 1000)的1000ms超时仅在单次无数据时退出,若数据分批到达,超时后直接break会截断不完整数据。
修复后的串口读取代码:
// 用字节数组存储原始数据,避免编码问题 ByteArrayOutputStream serialDataBuffer = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int totalBytesRead = 0; int MAX_DATA_SIZE = 1024; int timeoutCount = 0; final int MAX_TIMEOUTS = 3; // 连续3次超时判定传输结束 try { serialPort.open(usbManager.openDevice(serialPort.getDriver().getDevice())); serialPort.setParameters(9600, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE); while (true) { int bytesRead = serialPort.read(buffer, 1000); if (bytesRead > 0) { timeoutCount = 0; // 重置超时计数器 serialDataBuffer.write(buffer, 0, bytesRead); totalBytesRead += bytesRead; // 用字节终止符判断(示例用0x00,根据实际协议调整) byte[] tempData = serialDataBuffer.toByteArray(); if (tempData.length > 0 && tempData[tempData.length - 1] == 0x00) { break; } if (totalBytesRead >= MAX_DATA_SIZE) { break; } } else { timeoutCount++; if (timeoutCount >= MAX_TIMEOUTS) { break; // 连续超时判定传输完成 } } } // 指定编码转换为字符串 dataFromSerial = new String(serialDataBuffer.toByteArray(), StandardCharsets.UTF_8); } catch (IOException e) { e.printStackTrace(); } finally { try { serialPort.close(); } catch (IOException e) { e.printStackTrace(); } }
二、NFC标签写入失败的关键问题
1. NFC_Write命令未包含NDEF数据
当前nfcWriteCommand仅定义了命令头,未将ndefData拼接到命令中,导致标签接收不到要写入的有效数据。
2. 命令长度字段赋值错误
nfcWriteCommand[1]设为0x00,但该字段需对应整个命令的总长度(减去起始字节和长度字节本身),长度错误会导致标签拒绝执行命令。
3. NDEF长度计算错误
原代码中(byte) (ndefData.length + 1)多计算了1个字节,会导致标签解析数据时出错。
修复后的sendFileToTag函数:
public boolean sendFileToTag(Tag detectedTag, int sectorOrPage) { try { String filePath = "/storage/self/primary/Upload_in_NFC.txt"; String fileData = readFileAsString(filePath); byte[] ndefData = encodeNdefData(fileData); if (ndefData == null || ndefData.length == 0) { showToast("NDEF数据编码失败"); return false; } // 计算命令总长度:起始字节(1)+长度字节(1)+命令字节(1)+扇区(1)+NDEF长度(1)+起始标记(1)+NDEF数据长度 int totalCommandLength = 6 + ndefData.length; byte[] nfcWriteCommand = new byte[totalCommandLength]; nfcWriteCommand[0] = (byte) 0xAA; // 起始字节 nfcWriteCommand[1] = (byte) (totalCommandLength - 2); // 长度字段:总长度减起始、长度字节 nfcWriteCommand[2] = 0x2C; // 命令字节(注意注释标注的是0x94,需确认实际协议) nfcWriteCommand[3] = (byte) sectorOrPage; nfcWriteCommand[4] = (byte) ndefData.length; // NDEF数据实际长度 nfcWriteCommand[5] = 0x01; // NDEF起始标记 // 复制NDEF数据到命令末尾 System.arraycopy(ndefData, 0, nfcWriteCommand, 6, ndefData.length); byte[] responseData = sendNFCCommand(detectedTag, nfcWriteCommand); if (responseData != null && responseData.length > 0 && responseData[0] == (byte) 0x00) { byte[] cardNumber = Arrays.copyOfRange(responseData, 1, responseData.length); System.out.println("文件数据写入NFC标签成功"); System.out.println("卡号: " + asciiToHex(new String(cardNumber, StandardCharsets.US_ASCII))); return true; } else { showToast("NFC写入错误"); } } catch (IOException e) { e.printStackTrace(); showToast("读取文件失败"); } return false; }
三、其他潜在问题
- 文件写入逻辑局限性:
writeDataToFile仅处理TNF_WELL_KNOWN类型的文本记录,若NFC标签包含URI等其他类型记录,会丢失数据,可扩展判断逻辑支持更多NDEF类型。 - 权限问题:Android 10+需申请
MANAGE_EXTERNAL_STORAGE权限才能访问/storage/self/primary下的文件,否则会出现文件读取失败。
内容的提问来源于stack exchange,提问作者Wan Ammar
相关产品推荐
相关产品推荐

