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

使用jSerialComm的Java串口通信对特定设备出现数据损坏问题

Java串口通信(jSerialComm)与特定设备通信时数据损坏问题

设备配置参数

Port: COM3
BaudRate: 2400
Parity: EVEN
Databits: 7
Stopbits: 1

问题背景

  • Java程序基于jSerialComm库实现串口通信,与多数设备通信正常,但和某特定设备通信时接收数据损坏
  • 同设备用C#原生串口实现通信时,可正常接收数据
  • 已尝试调整Java程序的波特率和奇偶校验设置,问题未解决

Java程序代码与日志

连接设备代码

SerialPort[] serialPorts = SerialPort.getCommPorts();
for (SerialPort port : serialPorts) {
    if (DEVICE_PORT.equals(port.getSystemPortName())) {
        bolFound = true;
        serialPort = port;
        try {
            log.info("Opening port '" + DEVICE_PORT + "'...");
            log.info("Connecting to device '" + DEVICE_NAME + "'...");

            serialPort.setComPortParameters(DEVICE_RATE, DEVICE_DATABITS, DEVICE_STOPBITS, DEVICE_PARITY);
            serialPort.addDataListener(this);
            serialPort.openPort();

...........

数据监听代码

@Override
public int getListeningEvents() {
    return SerialPort.LISTENING_EVENT_DATA_AVAILABLE;
}

@Override
public void serialEvent(SerialPortEvent event) {
    switch (event.getEventType()) {
        case SerialPort.LISTENING_EVENT_DATA_AVAILABLE:
            readComm();
            break;
        default:
            log.info("XXX default");
            break;
    }
}

public void readComm() {
    log.info(AppConfig.getInstance().getProperty(AppConfig.KEY_TEST_PORT, String.class) + " Reading Comm...");
    byte[] readBuffer = new byte[1024];
    try {
        inputStream = serialPort.getInputStream();
        int len = 0;
            
        while ((len = inputStream.read(readBuffer)) != -1) {
            log.info("Real Time Response:" + new String(readBuffer, 0, len));
            value += new String(readBuffer, 0, len);
            break;
        }
        log.info("value:" + value);

        if (isDataReady) {
            // process data
            value = ""; //reset data
        }

    } catch (IOException e) {
        intNumberOfFailure++;
    }
}

Java程序日志

2023-11-09 10:38:58.165  INFO 21320 [Thread-117 thread] h.h.c.v.l.BaseListener                   : Trying to init Test Listener (COM5)...
2023-11-09 10:38:58.350  INFO 21320 [Thread-117 thread] h.h.c.v.l.BaseListener                   : Opening port 'COM5'...
2023-11-09 10:38:58.350  INFO 21320 [Thread-117 thread] h.h.c.v.l.BaseListener                   : Connecting to device 'Testing'...
2023-11-09 10:38:58.350  INFO 21320 [Thread-117 thread] h.h.c.v.l.BaseListener                   : Opening port 'COM5' Success
2023-11-09 10:38:58.350  INFO 21320 [Thread-117 thread] h.h.c.v.l.BaseListener                   : Connecting to device 'Testing' Success
2023-11-09 10:38:59.211  INFO 21320 [Thread-120 thread] h.h.c.v.l.TestListener                   : COM5 Reading Comm...
2023-11-09 10:38:59.215  INFO 21320 [Thread-120 thread] h.h.c.v.l.TestListener                   : Real Time Response:[ 
2023-11-09 10:38:59.217  INFO 21320 [Thread-120 thread] h.h.c.v.l.TestListener                   : value:[ 
2023-11-09 10:38:59.219  INFO 21320 [Thread-120 thread] h.h.c.v.l.TestListener                   : COM5 Reading Comm...
2023-11-09 10:38:59.221  INFO 21320 [Thread-120 thread] h.h.c.v.l.TestListener                   : Real Time Response:l
2023-11-09 10:38:59.222  INFO 21320 [Thread-120 thread] h.h.c.v.l.TestListener                   : value:[ l
2023-11-09 10:38:59.225  INFO 21320 [Thread-120 thread] h.h.c.v.l.TestListener                   : COM5 Reading Comm...
2023-11-09 10:38:59.227  INFO 21320 [Thread-120 thread] h.h.c.v.l.TestListener                   : Real Time Response:@ 1
2023-11-09 10:38:59.229  INFO 21320 [Thread-120 thread] h.h.c.v.l.TestListener                   : value:[ l@   1
2023-11-09 10:39:00.215  INFO 21320 [Thread-120 thread] h.h.c.v.l.TestListener                   : COM5 Reading Comm...
2023-11-09 10:39:00.215  INFO 21320 [Thread-120 thread] h.h.c.v.l.TestListener                   : Real Time Response:{=Um%
2023-11-09 10:39:00.226  INFO 21320 [Thread-120 thread] h.h.c.v.l.TestListener                   : value:[ l@   1{=Um%
2023-11-09 10:39:00.230  INFO 21320 [Thread-120 thread] h.h.c.v.l.TestListener                   : COM5 Reading Comm...
2023-11-09 10:39:00.232  INFO 21320 [Thread-120 thread] h.h.c.v.l.TestListener                   : Real Time Response:l
2023-11-09 10:39:00.232  INFO 21320 [Thread-120 thread] h.h.c.v.l.TestListener                   : value:[ l@   1{=Um%l
2023-11-09 10:39:00.236  INFO 21320 [Thread-120 thread] h.h.c.v.l.TestListener                   : COM5 Reading Comm...
2023-11-09 10:39:00.237  INFO 21320 [Thread-120 thread] h.h.c.v.l.TestListener                   : Real Time Response: ,a
2023-11-09 10:39:00.238  INFO 21320 [Thread-120 thread] h.h.c.v.l.TestListener                   : value:[ l@   1{=Um%l ,a
2023-11-09 10:39:00.241  INFO 21320 [Thread-120 thread] h.h.c.v.l.TestListener                   : COM5 Reading Comm...
2023-11-09 10:39:00.242  INFO 21320 [Thread-120 thread] h.h.c.v.l.TestListener                   : Real Time Response: 
2023-11-09 10:39:00.243  INFO 21320 [Thread-120 thread] h.h.c.v.l.TestListener                   : value:[ l@   1{=Um%l ,a 
2023-11-09 10:39:01.202  INFO 21320 [Thread-120 thread] h.h.c.v.l.TestListener                   : COM5 Reading Comm...
2023-11-09 10:39:01.217  INFO 21320 [Thread-120 thread] h.h.c.v.l.TestListener                   : Real Time Response:  
2023-11-09 10:39:01.217  INFO 21320 [Thread-120 thread] h.h.c.v.l.TestListener                   : value:[ l@   1{=Um%l ,a   

C#程序代码与日志

连接设备代码

string portName = "COM3";
int baudRate = 2400;
Parity parity = Parity.Even;
int dataBits = 7;
StopBits stopBits = StopBits.One;

_serialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits);

_serialPort.DataReceived += SerialPort_DataReceived;

_serialPort.Open();

数据监听代码

Console.WriteLine("Serial port opened. Press Enter to stop reading.");
_logWriter = new StreamWriter("log.txt", true);

while (true)
{
    if (_serialPort.BytesToRead > 0)
    {
        string data = _serialPort.ReadExisting();
        DateTime now = DateTime.Now;

        string logMessage = $"[{now}] Received data: {data}";

        Console.WriteLine(logMessage);
        _logWriter.WriteLine($"[{now}] Received data: {data}");
        _logWriter.Flush(); // Flush the buffer to ensure data is written immediately

    }
}

C#程序日志

[09/11/2023 10:53:09] Received data: US,+000091.50 kg

[09/11/2023 10:53:09] Received data: US,+000091.50 kg

[09/11/2023 10:53:10] Received data: US,+000091.50 kg

[09/11/2023 10:53:10] Received data: US,+000091.50 kg

[09/11/2023 10:53:10] Received data: S
[09/11/2023 10:53:10] Received data: T,+171.4 cm

[09/11/2023 10:53:11] Received data: ST,+000091.50 kg

[09/11/2023 10:53:11] Received data: US,+0000
[09/11/2023 10:53:11] Received data: 91.50 kg

[09/11/2023 10:53:12] Received data: US,+000091.50 kg

[09/11/2023 10:53:12] Received data: US,+000091.50 kg

[09/11/2023 10:53:13] Received data: US,+00
[09/11/2023 10:53:13] Received data: 0091.50 kg

[09/11/2023 10:53:13] Received data: US,+000091.50 kg

问题分析与解决方案

可能原因

  1. 串口参数映射错误:jSerialComm的参数常量与设备要求的映射可能存在偏差,比如7数据位、偶校验的常量定义是否正确对应SerialPort.DATABITS_7和SerialPort.PARITY_EVEN。
  2. 流控制设置差异:C#原生串口默认可能启用了XON/XOFF流控制,而jSerialComm默认未启用,导致设备发送的数据无法被正确接收。
  3. 读取逻辑与编码差异:Java代码单次读取后直接break,未读取完缓存数据;且字符串转换未指定ASCII编码(C#默认用ASCII),导致字节转字符串时损坏。
  4. 端口初始化顺序问题:jSerialComm中参数设置顺序可能影响生效,需确保先配置所有参数再打开端口。

修复步骤

  1. 确认参数常量正确性
    确保DEVICE_DATABITS为SerialPort.DATABITS_7,DEVICE_PARITY为SerialPort.PARITY_EVEN,DEVICE_STOPBITS为SerialPort.STOPBITS_1。

  2. 统一编码方式
    字符串转换时指定ASCII编码,与C#保持一致:

    log.info("Real Time Response:" + new String(readBuffer, 0, len, StandardCharsets.US_ASCII));
    value += new String(readBuffer, 0, len, StandardCharsets.US_ASCII);
    
  3. 优化读取逻辑
    读取所有可用字节,复用输入流(不要每次读取都重新获取):

    // 初始化时获取一次输入流
    private InputStream inputStream;
    
    // 端口打开成功后初始化
    inputStream = serialPort.getInputStream();
    
    public void readComm() {
        log.info(AppConfig.getInstance().getProperty(AppConfig.KEY_TEST_PORT, String.class) + " Reading Comm...");
        byte[] readBuffer = new byte[1024];
        try {
            int available = inputStream.available();
            if (available > 0) {
                int len = inputStream.read(readBuffer, 0, available);
                if (len > 0) {
                    String received = new String(readBuffer, 0, len, StandardCharsets.US_ASCII);
                    log.info("Real Time Response:" + received);
                    value += received;
                }
            }
            log.info("value:" + value);
    
            if (isDataReady) {
                // process data
                value = ""; //reset data
            }
    
        } catch (IOException e) {
            intNumberOfFailure++;
        }
    }
    
  4. 配置流控制与超时
    添加流控制和超时配置,匹配C#默认行为:

    serialPort.setFlowControl(SerialPort.FLOW_CONTROL_XONXOFF_IN_ENABLED | SerialPort.FLOW_CONTROL_XONXOFF_OUT_ENABLED);
    serialPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_SEMI_BLOCKING, 100, 0);
    
  5. 调整初始化顺序
    先配置所有参数再打开端口:

    serialPort.setComPortParameters(DEVICE_RATE, DEVICE_DATABITS, DEVICE_STOPBITS, DEVICE_PARITY);
    serialPort.setFlowControl(...);
    serialPort.setComPortTimeouts(...);
    serialPort.addDataListener(this);
    serialPort.openPort();
    

内容的提问来源于stack exchange,提问作者LEE Hin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 21:38:10