1.下載
地址:http://fizzed.com/oss/rxtx-for-java
2.部署到Windows
下載完成後將rxtxParallel.dll、rxtxSerial.dll、文件拷貝到Java jdk的bin目錄下(如圖)
然後把RXTXcomm.jar包引入到項目中或者使用maven引入都可以,兩種方式選一種就可以:
方式一: 本地jar包直接引入
在項目根目錄下新建lib文件夾並導入RXTXcomm.jar,然後在pom中引入本地jar包即可
<dependency>
<groupId>com.test</groupId>
<artifactId>rxtxcomm</artifactId>
<version>2.2</version>
<scope>system</scope>
<systemPath>${basedir}/lib/RXTXcomm.jar</systemPath>
</dependency>
方式二 : maven引入,在pom中寫入如下內容即可
<dependency>
<groupId>org.bidib.jbidib.org.qbang.rxtx</groupId>
<artifactId>rxtxcomm</artifactId>
<version>2.2</version>
</dependency>
3.測試編碼:
import gnu.io.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.TooManyListenersException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class SerialPortDataHandle extends Thread implements SerialPortEventListener {
private static final Logger logger = LoggerFactory.getLogger(SerialPortDataHandle.class);
// 通訊端口管理,控制對通信端口的訪問的中心類
static CommPortIdentifier portManager;
// 有效連接上的端口的枚舉
static Enumeration<?> portList;
// 串口輸入流引用
static InputStream inputStream;
// 串口輸出流引用
static OutputStream outputStream;
// 串口對象引用
static SerialPort serialPort;
// 堵塞隊列:用來存放串口發送到服務端的數據
private BlockingQueue<String> msgQueue = new LinkedBlockingQueue();
// 線程控制標識
private boolean flag = true;
public void serialEvent(SerialPortEvent event) {
switch (event.getEventType()) {
/*
* SerialPortEvent.BI:/*Break interrupt,通訊中斷
* SerialPortEvent.OE:/*Overrun error,溢位錯誤
* SerialPortEvent.FE:/*Framing error,傳幀錯誤
* SerialPortEvent.PE:/*Parity error,校驗錯誤
* SerialPortEvent.CD:/*Carrier detect,載波檢測
* SerialPortEvent.CTS:/*Clear to send,清除發送
* SerialPortEvent.DSR:/*Data set ready,數據設備就緒
* SerialPortEvent.RI:/*Ring indicator,響鈴指示
* SerialPortEvent.OUTPUT_BUFFER_EMPTY:/*Output buffer is empty,輸出緩衝區清空
*/
case SerialPortEvent.BI:
case SerialPortEvent.OE:
case SerialPortEvent.FE:
case SerialPortEvent.PE:
case SerialPortEvent.CD:
case SerialPortEvent.CTS:
case SerialPortEvent.DSR:
case SerialPortEvent.RI:
case SerialPortEvent.OUTPUT_BUFFER_EMPTY: break;
// 當有可用數據時讀取數據
case SerialPortEvent.DATA_AVAILABLE:
// 數據接收緩衝容器
byte[] readBuffer = new byte[0];
try {
readBuffer = new byte[inputStream.available()];
} catch (IOException e) {
e.printStackTrace();
}
try {
// 存儲待接收讀取字節數大小
int numBytes = 0;
while (inputStream.available() > 0) {
numBytes = inputStream.read(readBuffer);
if (numBytes > 0) {
msgQueue.add(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
.format(new Date()) + " 收到的串口發送數據爲:"+ new String(readBuffer));
// 數據接收緩衝容器清空初始化
readBuffer = new byte[0];
}
}
} catch (IOException e) {
logger.error("IO異常", e);
}
break;
}
}
public int init() {
// 通過串口通信管理類獲得當前連接上的端口列表
//(獲取一個枚舉對象,該CommPortIdentifier對象包含系統中每個端口的對象集[串口、並口])
portList = CommPortIdentifier.getPortIdentifiers();
while (portList.hasMoreElements()) {
// 獲取相應串口對象
portManager = (CommPortIdentifier) portList.nextElement();
/*
* 判斷端口類型是否爲串口
* PORT_SERIAL = 1; 【串口】
* PORT_PARALLEL = 2; 【並口】
* PORT_I2C = 3; 【I2C】
* PORT_RS485 = 4; 【RS485】
* PORT_RAW = 5; 【RAW】
*/
if (portManager.getPortType() == CommPortIdentifier.PORT_SERIAL) {
logger.info("串口設備名稱:" + portManager.getName());
// 判斷模擬COM4串口存在,就打開該串口
if (portManager.getName().equals("COM4")) {
logger.info("測試串口設備名稱:" + portManager.getName());
try {
if (serialPort==null) {
// 打開串口,設置名字爲COM_4(自定義),延遲阻塞時等待3000毫秒(賦值給預設的串口引用)
serialPort = (SerialPort)portManager.open("COM4", 3000);
logger.info("串口設備COM4已打開");
}
} catch (PortInUseException e) {
logger.error("串口使用異常", e);
return 0;
}
// 在串口引用不爲空時進行下述操作
if (serialPort!=null) {
// 1. 設置串口的輸入輸出流引用
try {
inputStream = serialPort.getInputStream();
outputStream = serialPort.getOutputStream();
} catch (IOException e) {
logger.error("串口輸入輸出IO異常", e);
return 0;
}
// 2. 設置串口監聽器
try {
serialPort.addEventListener(this);
} catch (TooManyListenersException e) {
logger.error("串口監聽器添加異常", e);
return 0;
}
// 設置監聽器在有數據時通知生效
serialPort.notifyOnDataAvailable(true);
// 3. 設置串口相關讀寫參數
try {
// 比特率、數據位、停止位、校驗位
serialPort.setSerialPortParams(115200,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
} catch (UnsupportedCommOperationException e) {
logger.error("串口設置操作異常", e);
return 0;
}
return 1;
}
return 0;
}
}
}
return 0;
}
@Override
public void run() {
try {
logger.info("串口線程已運行");
while (flag) {
// 如果堵塞隊列中存在數據就將其輸出
if (msgQueue.size() > 0) {
// take() 取走BlockingQueue裏排在首位的對象
// 若BlockingQueue爲空,阻斷進入等待狀態直到Blocking有新的對象被加入爲止
String msg = msgQueue.take();
logger.info(msg);
//echo數據
sendToPort(serialPort, msg.getBytes());
}
}
} catch (InterruptedException e) {
logger.error("線程執行異常", e);
}
}
public void stopGetDataBySerialPort() {
this.flag = false;
}
/**
* 往串口發送數據
*
* @param serialPort 串口對象
* @param data 待發送數據
*/
public static void sendToPort(SerialPort serialPort, byte[] data) {
OutputStream out = null;
try {
out = serialPort.getOutputStream();
out.write(data);
out.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
SerialPortDataHandle handle = new SerialPortDataHandle();
int i = handle.init();
if (i == 1) {
// 線程啓動
handle.start();
}
}
}
4. 測試
需要下載兩個調試工具:XCOM V2.0、vspd(Configure Virtual Serial Port Driver)
先在vspd中新增COMM4和COMM5端口如圖,這裏COMM4和COMM5是連接在一起的,也就是說如果我在COMM5發送數據後COMM4就能收到
然後我們打開XCOM V2.0,然後配置串口參數如圖(我選擇的是COM5),這樣我們在COM5發送消息後,COMM4應該就能收到了