嵌入式系統與主控系統間的全雙工串口通訊是工業自動化、儀器儀表、智能設備的核心需求。本文提供一個開箱即用的 Java 串口通訊類庫,封裝了 JavaComm API 的複雜細節,通過生產者-消費者模式實現非阻塞收發,包含串口初始化、緩衝區管理、讀取線程、應用接口四大模塊,附帶完整測試例程與部署指南。
public class SerialBean {
private static String portName;
private CommPortIdentifier portId;
private SerialPort serialPort;
private static OutputStream out;
private static InputStream in;
private SerialBuffer buffer;
private ReadSerial readerThread;
public SerialBean(int portID) { portName = "COM" + portID; }
public int initialize() {
try {
portId = CommPortIdentifier.getPortIdentifier(portName);
serialPort = (SerialPort) portId.open("Serial_Communication", 2000);
in = serialPort.getInputStream();
out = serialPort.getOutputStream();
// 9600, 8, 1, None - 標準工業默認配置
serialPort.setSerialPortParams(9600,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
// 啟動讀取線程
buffer = new SerialBuffer();
readerThread = new ReadSerial(buffer, in);
readerThread.start();
return 1; // 成功
} catch (Exception e) {
return -1; // 失敗
}
}
public String readPort(int length) {
return buffer.getMsg(length); // 阻塞直到足夠數據
}
public void writePort(String msg) {
try {
for (char c : msg.toCharArray()) out.write(c);
} catch (IOException ignored) {}
}
public void closePort() {
readerThread.stop(); // 注意:stop() 已棄用,生產環境建議用中斷標誌
serialPort.close();
}
}
public class SerialBuffer {
private String content = "";
private int lengthNeeded = 1;
private boolean available = false;
// 讀取指定長度(阻塞等待)
public synchronized String getMsg(int length) {
lengthNeeded = length;
notifyAll();
while (lengthNeeded > content.length()) {
available = false;
try { wait(); } catch (InterruptedException ignored) {}
}
String msg = content.substring(0, lengthNeeded);
content = content.substring(lengthNeeded);
lengthNeeded = 1;
notifyAll();
return msg;
}
// 寫入單字符(喚醒等待讀取線程)
public synchronized void putChar(int c) {
content += (char) c;
if (lengthNeeded <= content.length()) available = true;
notifyAll();
}
}
public class ReadSerial extends Thread {
private SerialBuffer buffer;
private InputStream port;
public ReadSerial(SerialBuffer buffer, InputStream port) {
this.buffer = buffer;
this.port = port;
}
@Override
public void run() {
try {
while (true) {
int c = port.read(); // 阻塞讀取
if (c != -1) buffer.putChar(c);
}
} catch (IOException ignored) {} // 串口關閉觸發異常退出
}
}
| 方案 | 硬件連接 | 軟件配置 |
|---|---|---|
| 單機回環 | RS-232 交叉線連接 COM1-COM2 | COM1 運行 SerialExample,COM2 運行超級終端 |
| 雙機通訊 | RS-232 直連線連接兩機 COM1 | 一端運行例程,一端運行超級終端 |