Java利用RxtxComm收發串口數據

1.下載

地址:http://fizzed.com/oss/rxtx-for-java

2.部署到Windows

下載完成後將rxtxParallel.dllrxtxSerial.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應該就能收到了

 

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