1.准備工作
在進行串口連接通訊前,必須保證你當前操作電腦上有可用且閑置的串口。因為一般的電腦上只有一個或者兩個串口,如COM1或COM2,但大多數情況下,這些串口可能會被其他的程序或者應用所占用,所以此時我們可以借助工具,在我們的電腦上建立虛擬串口。
先下載一個叫Virtual Serial Port的軟件,通過這個軟件可以創建新的虛擬串口,如下圖所示:

通過圖中的添加串口即可進行新虛擬串口的創建,並且一般都是成對創建。
有了虛擬串口之后,為了方便測試新建串口是否可用,我們可以再下載一款串口測試軟件,我用的是一個串口調試助手,如下圖:

通過測試,發現我所添加的虛擬串口COM3和COM4是可以用的,那么接下來,我們就可以關閉其中一個,通過我們的JAVA程序來進行與該虛擬串口的信息交互了。
2.JAVA程序的操作
在進行程序編寫之前,我們需要下載幾個文件,才能使我們的程序進行串口通訊的操作。
首先需要下載如下圖中的三個文件:

並將RXTXcomm.jar這個包通過集成工具的構建路徑添加到我們的項目之中;其次將 rxtxParallel.dll 和 rxtxSerial.dll 這兩個文件放到我們的JDK安裝目錄中的bin文件夾中。
這兩個文件必須添加到指定位置,否則后面程序在運行時將會報錯找不到文件。(需要注意:這幾個文件按操作系統分32位和64位,各位需要根據自己電腦的系統下載對應的版本,不然也會報錯).
接下來可以開始我們的代碼編寫了,為了方便使用,我們肯定是需要有一個SerialPort串口工具類,如下:
-
package com.cams.CaMSMobileService.SerialPort;
-
-
import gnu.io.CommPort;
-
import gnu.io.CommPortIdentifier;
-
import gnu.io.NoSuchPortException;
-
import gnu.io.PortInUseException;
-
import gnu.io.SerialPort;
-
import gnu.io.SerialPortEventListener;
-
import gnu.io.UnsupportedCommOperationException;
-
-
import java.io.IOException;
-
import java.io.InputStream;
-
import java.io.OutputStream;
-
import java.util.ArrayList;
-
import java.util.Enumeration;
-
import java.util.TooManyListenersException;
-
-
import com.cams.CaMSMobileService.SerialPort.exception.NoSuchPort;
-
import com.cams.CaMSMobileService.SerialPort.exception.NotASerialPort;
-
import com.cams.CaMSMobileService.SerialPort.exception.PortInUse;
-
import com.cams.CaMSMobileService.SerialPort.exception.ReadDataFromSerialPortFailure;
-
import com.cams.CaMSMobileService.SerialPort.exception.SendDataToSerialPortFailure;
-
import com.cams.CaMSMobileService.SerialPort.exception.SerialPortInputStreamCloseFailure;
-
import com.cams.CaMSMobileService.SerialPort.exception.SerialPortOutputStreamCloseFailure;
-
import com.cams.CaMSMobileService.SerialPort.exception.SerialPortParameterFailure;
-
import com.cams.CaMSMobileService.SerialPort.exception.TooManyListeners;
-
-
public class SerialPortManager {
-
-
/**
-
* 查找所有可用端口
-
*
-
* @return 可用端口名稱列表
-
*/
-
-
public static final ArrayList<String> findPort() {
-
// 獲得當前所有可用串口
-
Enumeration<CommPortIdentifier> portList = CommPortIdentifier
-
.getPortIdentifiers();
-
ArrayList<String> portNameList = new ArrayList<String>();
-
// 將可用串口名添加到List並返回該List
-
while (portList.hasMoreElements()) {
-
String portName = portList.nextElement().getName();
-
portNameList.add(portName);
-
}
-
return portNameList;
-
}
-
-
/**
-
* 打開串口
-
*
-
* @param portName
-
* 端口名稱
-
* @param baudrate
-
* 波特率
-
* @return 串口對象
-
* @throws SerialPortParameterFailure
-
* 設置串口參數失敗
-
* @throws NotASerialPort
-
* 端口指向設備不是串口類型
-
* @throws NoSuchPort
-
* 沒有該端口對應的串口設備
-
* @throws PortInUse
-
* 端口已被占用
-
*/
-
public static final SerialPort openPort(String portName, int baudrate)
-
throws SerialPortParameterFailure, NotASerialPort, NoSuchPort,
-
PortInUse {
-
try {
-
// 通過端口名識別端口
-
CommPortIdentifier portIdentifier = CommPortIdentifier
-
.getPortIdentifier(portName);
-
// 打開端口,設置端口名與timeout(打開操作的超時時間)
-
CommPort commPort = portIdentifier.open(portName, 2000);
-
// 判斷是不是串口
-
if (commPort instanceof SerialPort) {
-
SerialPort serialPort = (SerialPort) commPort;
-
-
try {
-
// 設置串口的波特率等參數
-
serialPort.setSerialPortParams(baudrate,
-
SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
-
SerialPort.PARITY_NONE);
-
} catch (UnsupportedCommOperationException e) {
-
throw new SerialPortParameterFailure();
-
}
-
return serialPort;
-
} else {
-
// 不是串口
-
throw new NotASerialPort();
-
}
-
} catch (NoSuchPortException e1) {
-
throw new NoSuchPort();
-
} catch (PortInUseException e2) {
-
throw new PortInUse();
-
}
-
}
-
-
/**
-
* 關閉串口
-
*
-
* @param serialport
-
* 待關閉的串口對象
-
*/
-
public static void closePort(SerialPort serialPort) {
-
if (serialPort != null) {
-
serialPort.close();
-
serialPort = null;
-
}
-
}
-
-
/**
-
* 向串口發送數據
-
*
-
* @param serialPort
-
* 串口對象
-
* @param order
-
* 待發送數據
-
* @throws SendDataToSerialPortFailure
-
* 向串口發送數據失敗
-
* @throws SerialPortOutputStreamCloseFailure
-
* 關閉串口對象的輸出流出錯
-
*/
-
public static void sendToPort(SerialPort serialPort, byte[] order)
-
throws SendDataToSerialPortFailure,
-
SerialPortOutputStreamCloseFailure {
-
OutputStream out = null;
-
try {
-
out = serialPort.getOutputStream();
-
out.write(order);
-
out.flush();
-
} catch (IOException e) {
-
throw new SendDataToSerialPortFailure();
-
} finally {
-
try {
-
if (out != null) {
-
out.close();
-
out = null;
-
}
-
} catch (IOException e) {
-
throw new SerialPortOutputStreamCloseFailure();
-
}
-
}
-
}
-
-
/**
-
* 從串口讀取數據
-
*
-
* @param serialPort
-
* 當前已建立連接的SerialPort對象
-
* @return 讀取到的數據
-
* @throws ReadDataFromSerialPortFailure
-
* 從串口讀取數據時出錯
-
* @throws SerialPortInputStreamCloseFailure
-
* 關閉串口對象輸入流出錯
-
*/
-
public static byte[] readFromPort(SerialPort serialPort)
-
throws ReadDataFromSerialPortFailure,
-
SerialPortInputStreamCloseFailure {
-
InputStream in = null;
-
byte[] bytes = null;
-
try {
-
in = serialPort.getInputStream();
-
// 獲取buffer里的數據長度
-
int bufflenth = in.available();
-
while (bufflenth != 0) {
-
// 初始化byte數組為buffer中數據的長度
-
bytes = new byte[bufflenth];
-
in.read(bytes);
-
bufflenth = in.available();
-
}
-
} catch (IOException e) {
-
throw new ReadDataFromSerialPortFailure();
-
} finally {
-
try {
-
if (in != null) {
-
in.close();
-
in = null;
-
}
-
} catch (IOException e) {
-
throw new SerialPortInputStreamCloseFailure();
-
}
-
}
-
return bytes;
-
}
-
-
/**
-
* 添加監聽器
-
*
-
* @param port
-
* 串口對象
-
* @param listener
-
* 串口監聽器
-
* @throws TooManyListeners
-
* 監聽類對象過多
-
*/
-
public static void addListener(SerialPort port,
-
SerialPortEventListener listener) throws TooManyListeners {
-
try {
-
// 給串口添加監聽器
-
port.addEventListener(listener);
-
// 設置當有數據到達時喚醒監聽接收線程
-
port.notifyOnDataAvailable( true);
-
// 設置當通信中斷時喚醒中斷線程
-
port.notifyOnBreakInterrupt( true);
-
} catch (TooManyListenersException e) {
-
throw new TooManyListeners();
-
}
-
}
-
}
有了工具類之后,接下來我們就可以開始測試串口通訊了,如下:


到這里串口通訊測試的也差不多了。可能自己做的項目中需要自己做兩個串口,一個client端和一個server端。為了使串口操作變的可視化,大家也可以使用JFrame來進行操作窗口模擬,這里就不做多的介紹了。