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 可用端口名稱列表
*/
@SuppressWarnings("unchecked")
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來進行操作窗口模擬,這裏就不做多的介紹了。