You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

串口传输数据持续缓冲,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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 17:44:59