使用RXTXcomm進行串口通信

RXTXcomm 串口通信

虛擬串口和串口調試助手的使用

  • 虛擬串口軟件:VSPDhttps://www.eltima.com/cn/products/vspdxp/

    • VSPD會自動識別出本臺計算上有幾個物理串口,例如本機只有一個物理串口COM1。在右側端口管理的分頁中,添加虛擬端口。虛擬端口是成對出現的,如COM2和COM3,其編號由VSPD自動檢測本地物理串口資源後,自動爲虛擬串口排號。單擊“Add pair”按鈕爲計算機添加虛擬串口組對。

      爲何是組對出現,COM2->COM3和COM3->COM2,串口通信是異步的,允許發送數據的同時接收數據,數據流向是雙向的。組對出現我們可以通過串口調試助手分別從兩端進行調試。
      在這裏插入圖片描述

  • 串口調試助手:COMHelper,需要可留言私信你滴郵箱,打包發你。

    • 開箱即用,開啓串口,點擊即用。

使用效果如下:
在這裏插入圖片描述

Java RXTXcomm 實現串口通信並調試

  • 下載RXTXcomm

  • 根據機器配置解壓縮文件夾,複製相關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 - 串口線程已運行
      
    • 通過串口調試工具進行數據發送,查看服務端控制檯輸出信息
      在這裏插入圖片描述

    • 查看虛擬端口狀態
      在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章