RXTXcomm 串口通信
虛擬串口和串口調試助手的使用
-
虛擬串口軟件:
VSPD
,https://www.eltima.com/cn/products/vspdxp/-
VSPD會自動識別出本臺計算上有幾個物理串口,例如本機只有一個物理串口COM1。在右側端口管理的分頁中,添加虛擬端口。虛擬端口是成對出現的,如COM2和COM3,其編號由VSPD自動檢測本地物理串口資源後,自動爲虛擬串口排號。單擊“Add pair”按鈕爲計算機添加虛擬串口組對。
爲何是組對出現,COM2->COM3和COM3->COM2,串口通信是異步的,允許發送數據的同時接收數據,數據流向是雙向的。組對出現我們可以通過串口調試助手分別從兩端進行調試。
-
-
串口調試助手:
COMHelper
,需要可留言私信你滴郵箱,打包發你。- 開箱即用,開啓串口,點擊即用。
使用效果如下:
Java RXTXcomm 實現串口通信並調試
-
下載RXTXcomm
- RXTXcomm提供了 Windows x64, x86, ia64 and Linux x86, x86_64等操作系統支持。http://fizzed.com/oss/rxtx-for-java
-
根據機器配置解壓縮文件夾,複製相關Jar包及DLL文件
RXTXcomm.jar
-><JAVA_HOME>\jre\lib\ext
rxtxSerial.dll
-><JAVA_HOME>\jre\bin
rxtxParallel.dll
-><JAVA_HOME>\jre\bin
-
將Jar包添加到項目lib中,IDE使用的是
IDEA
,項目構建方式爲Maven
-
創建
SerialPortDataHandle
類,繼承Thread
類,並實現SerialPortEventListener
接口,具體代碼如下: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; @Override 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[200]; 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[200]; } } } 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 (Objects.isNull(serialPort)) { // 打開串口,設置名字爲COM_4(自定義),延遲阻塞時等待3000毫秒(賦值給預設的串口引用) serialPort = (SerialPort)portManager.open("COM4", 3000); logger.info("串口設備COM4已打開"); } } catch (PortInUseException e) { logger.error("串口使用異常", e); return 0; } // 在串口引用不爲空時進行下述操作 if (Objects.nonNull(serialPort)) { // 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(9600, 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有新的對象被加入爲止 logger.info(msgQueue.take()); } } } catch (InterruptedException e) { logger.error("線程執行異常", e); } } public void stopGetDataBySerialPort() { this.flag = false; } public static void main(String[] args) { SerialPortDataHandle handle = new SerialPortDataHandle(); int i = handle.init(); if (i == 1) { // 線程啓動 handle.start(); } } }
-
啓動線程並測試(線程會佔用並開啓COM4串口,我們使用COM5串口進行通信測試,執行
main
方法前要從串口調試工具中關閉COM4串口,不然會出現gnu.io.PortInUseException: Unknown Application
異常)-
執行
main
方法,啓動線程15:34:59.083 [main] INFO com.jeesite.modules.hp.serialport.SerialPortDataHandle - 串口設備名稱:COM1 15:34:59.089 [main] INFO com.jeesite.modules.hp.serialport.SerialPortDataHandle - 串口設備名稱:COM2 15:34:59.089 [main] INFO com.jeesite.modules.hp.serialport.SerialPortDataHandle - 串口設備名稱:COM3 15:34:59.089 [main] INFO com.jeesite.modules.hp.serialport.SerialPortDataHandle - 串口設備名稱:COM4 15:34:59.089 [main] INFO com.jeesite.modules.hp.serialport.SerialPortDataHandle - 測試串口設備名稱:COM4 15:34:59.102 [main] INFO com.jeesite.modules.hp.serialport.SerialPortDataHandle - 串口設備COM4已打開 15:34:59.103 [Thread-0] INFO com.jeesite.modules.hp.serialport.SerialPortDataHandle - 串口線程已運行
-
通過串口調試工具進行數據發送,查看服務端控制檯輸出信息
-
查看虛擬端口狀態
-