首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 串列通訊完整指南:RS232 協議、Java Communications API 與實戰避坑

     編輯:Java 相關知識

串列通訊協議概覽

協議特點典型應用
RS232全雙工、點對點、短距離 (15m)、單端信號Modem、PLC、儀器儀表、舊式設備
RS485半雙工、多點總線、長距離 (1200m)、差分信號工業控制、多設備串聯
RS422全雙工、差分、長距離、點對點高速數據傳輸
USB熱插拔、高速、複雜協議棧現代外設、虛擬串口 (CDC/ACM)

本文聚焦RS232,Java 透過 javax.comm (Java Communications API) 操作。

RS232 硬體基礎

常見接腳 (DB9)

腳位名稱方向功能
2RXD輸入接收資料
3TXD輸出傳送資料
5GND—訊號地
7RTS輸出請求傳送 (硬體流控)
8CTS輸入清除傳送 (硬體流控)

三線制接法 (最常用)

設備 A (DTE)          設備 B (DTE)
TXD (3)  ──────────→  RXD (2)
RXD (2)  ←──────────  TXD (3)
GND (5)  ──────────   GND (5)

注意:若設備內部已交叉 TX/RX,則 2-2, 3-3, 5-5 直連即可

識別 TXD/RXD 小技巧

萬用表測量:TXD 對 GND 通常有 -3V 至 -15V 負電壓(空閒態標記)。

Java Communications API 安裝

三個關鍵檔案

  • comm.jar → JRE/lib/ext/ (擴展庫)
  • win32com.dll → 應用程式工作目錄 (user.dir) 或 JRE/bin/
  • javax.comm.properties → JRE/lib/ (驅動配置:Driver=com.sun.comm.Win32Driver)

Linux 替代方案

官方不提供 Linux 版,可用 RXTX 或 jSerialComm (現代、跨平台、無需安裝)。

核心 API 與程式碼實戰

1. 列舉可用串口

Enumeration<CommPortIdentifier> ports = CommPortIdentifier.getPortIdentifiers();
while (ports.hasMoreElements()) {
    CommPortIdentifier portId = ports.nextElement();
    if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
        System.out.println("發現串口: " + portId.getName()); // COM1, COM2, /dev/ttyS0
    }
}

2. 開啟串口並建立流

CommPortIdentifier portId = CommPortIdentifier.getPortIdentifier("COM1");
CommPort commPort = portId.open("MyApp", 2000); // 2秒超時

SerialPort serialPort = (SerialPort) commPort;

// 參數配置:9600, 8N1
serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, 
    SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);

// 獲取流
InputStream in = serialPort.getInputStream();
OutputStream out = serialPort.getOutputStream();

3. 兩種讀取模式

模式輪詢事件驅動
原理循環 in.read()實作 SerialPortEventListener
執行緒需獨立執行緒JVM 回調執行緒
CPU 佔用高 (需 sleep)低
即時性依賴 sleep 間隔即時
複雜度低中

事件驅動完整範例

serialPort.addEventListener(new SerialPortEventListener() {
    @Override
    public void serialEvent(SerialPortEvent event) {
        if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
            try {
                byte[] buffer = new byte[1024];
                int len = in.read(buffer);
                if (len > 0) {
                    String data = new String(buffer, 0, len, "UTF-8");
                    processData(data);
                }
            } catch (IOException e) { handleError(e); }
        }
    }
});
serialPort.notifyOnDataAvailable(true); // 開啟事件通知

4. 寫入資料

String cmd = "AT\r\n";
out.write(cmd.getBytes("ASCII"));
out.flush();

5. 關閉資源

// 正確順序
in.close();
out.close();
commPort.close(); // 釋放串口佔用權

實戰避坑指南

  1. 串口被佔用:PortInUseException → 確保關閉其他終端程式 (PuTTY, SecureCRT)
  2. 參數不匹配:波特率、資料位、停止位、奇偶校驗必須雙端一致
  3. 流控制:硬體流控 (RTS/CTS) 需硬體支援,軟體流控 (XON/XOFF) 可能干擾二進位資料
  4. 編碼問題:指定編碼 new String(bytes, "GBK"),避免平台預設編碼差異
  5. 緩衝區溢位:高速資料需調大 serialPort.setInputBufferSize()、setOutputBufferSize()
  6. JNI 崩潰:win32com.dll 版本不匹配 → 更新 JDK/Comm API 版本

現代替代:jSerialComm (推薦)

// Maven: com.fazecast:jSerialComm:2.10.4
SerialPort[] ports = SerialPort.getCommPorts();
SerialPort port = ports[0];
port.openPort();
port.setBaudRate(9600);
port.setNumDataBits(8);
port.setNumStopBits(1);
port.setParity(0);

port.addDataListener(new SerialPortDataListener() {
    @Override
    public int getListeningEvents() { return SerialPort.LISTENING_EVENT_DATA_AVAILABLE; }
    @Override
    public void serialEvent(SerialPortEvent event) {
        byte[] buffer = new byte[event.getReceivedData().length];
        int numRead = event.getReceivedData(buffer);
        System.out.println("收到: " + new String(buffer, 0, numRead));
    }
});

優勢:純 Java、零原生庫、跨平台、Maven 直接依賴、API 現代化。

總結

Java 串列通訊核心在於:正確安裝 Comm API/RXTX/jSerialComm → 參數雙端一致 → 選擇輪詢/事件模式 → 處理編碼/流控/緩衝。現代專案首選 jSerialComm,避開原生庫安裝地獄。理解 RS232 硬體層特性,是排查通訊異常的關鍵。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved