Java利用Rxtx進行串口通訊


最近在做傳感器數據采集的工作,底層是基於Zigbee的無線傳感網絡,所有數據采集到Zigbee協調器上然后通知上位機數據采集完成,上位機通過USB轉串口去讀取數據就可以了。那么問題來了,如何進行串口通訊呢?老板說你用Java寫個程序好了嘛,用Java寫串口程序也是醉了。實驗室也沒別人寫了,所以就讓我寫了。當我聽到要讓我用Java寫串口通訊程序的時候我本來是拒絕的,然后。。。就沒有然后了。。就只能寫了。

網上看了一下,最后用了一個開源的Java串口通訊庫RXTX做串口通訊,下面記錄一下RXTX的使用方法。

環境配置

RXTX做串口通訊,有一個jar包(RXTXcomm.jar)和一個rxtxSerial.dll(Windows環境下)或者librxtxSerial.so(Linux環境下),因為開發是在Windows上,但是工作是在Linux上,所以兩個都用到了。

Windows環境下

文檔里是這么寫的

Copy rxtxSerial.dll ---> <JAVA_HOME>\jre\bin

但是這個做了之后並不能用,會有一些很奇怪的問題,不知道是不是我的Java環境配置有問題還是怎么了,我是把dll文件copy到了C:\Windows\System32,然后一切正常,一直很奇怪,為什么要cp到<JAVA_HOME>\jre\bin呢?求解答!

Linux環境下

Copy librxtxSerial.so ---> <JAVA_HOME>/jre/lib/i386/

or

Copy librxtxSerial.so ---> <JAVA_HOME>/jre/lib/x86_64/

這個按照文檔沒問題。

小問題

我用的是rxtx-2.2pre2版本的,文檔里有寫運行時會報版本不匹配的WARNING,實際使用中的確也是這樣的,不過目前還沒有別的問題,不影響使用。


常用方法

1.查找端口


/**

     * 查找所有可用端口

     *

     * @return 所有端口列表

     */

    public static final ArrayList<String> findPort() {

        Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();//獲得所有串口

        ArrayList<String> portNameList = new ArrayList<>();

        //串口名字添加到List並返回

        while (portList.hasMoreElements()) {

            String portName = portList.nextElement().getName();

            portNameList.add(portName);

        }

        return portNameList;

    }

2.打開端口


    /**

     * 打開串口

     *

     * @param portName 端口名稱

     * @param baudrate 波特率

     * @return 串口對象

     */

    public static final SerialPort openPort(String portName, int baudrate) {

        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) {

                    LOGGER.error("Set Serialport Parameters failure", e);

                }

                System.out.println("Open " + portName + " sucessfully !");

                return serialPort;

            } else {

                LOGGER.error("This port is not a serialport");

                return null;

            }

        } catch (NoSuchPortException | PortInUseException e) {

            LOGGER.error("There is no " + portName + "or it's occupied!", e);

            return null;

        }

    }

3.發送數據


    /**

     * 發送數據

     *

     * @param serialPort 串口對象

     * @param order      命令字節

     */

    public void sendToPort(SerialPort serialPort, byte[] order) {

        try {

            OutputStream out = serialPort.getOutputStream();

            out.write(order);

            out.flush();

            out.close();

        } catch (IOException e) {

            LOGGER.error("Send to SerialPort failure", e);

        }

    }

4.讀取數據


    /**

     * 讀取數據

     *

     * @return 字節ArrayList

     */

    public byte[] readFromPort(InputStream inStream) {

        byte[] bytes = null;

        try {

            while (true) {

                //獲取buffer里的數據長度

                int bufflenth = inStream.available();

                if (0 == bufflenth) {

                    break;

                }

                bytes = new byte[bufflenth];

                inStream.read(bytes);

            }

        } catch (IOException e) {

            LOGGER.error("Read Data Failure", e);

        }

        return bytes;

    }


監聽器

1.實現監聽器

繼承SerialPortEventListener然后重寫serialEvent,然后再各個對應case里面寫代碼就好啦。


public class TestExample implements SerialPortEventListener {

    @Override

    public void serialEvent(SerialPortEvent serialPortEvent) {

        switch (serialPortEvent.getEventType()) {

            case SerialPortEvent.BI: // 10通訊中斷

            case SerialPortEvent.OE: // 7溢位錯誤

            case SerialPortEvent.FE: // 9幀錯誤

            case SerialPortEvent.PE: // 8奇偶校驗錯

            case SerialPortEvent.CD: // 6載波檢測

            case SerialPortEvent.CTS: // 3清除發送

            case SerialPortEvent.DSR: // 4數據設備准備好

            case SerialPortEvent.RI: // 5振鈴指示

            case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 2輸出緩沖區已清空

            case SerialPortEvent.DATA_AVAILABLE: // 1讀到可用數據時激活

        }

    }

}

2.給串口添加監聽器


    /**

     * 添加監聽器

     *

     * @param port     串口對象

     * @param listener 串口監聽器

     */

    public static void addListener(SerialPort port, SerialPortEventListener listener) {

        try {

            // 給串口添加監聽器

            port.addEventListener(listener);

            // 設置當有數據到達時喚醒監聽接收線程

            port.notifyOnDataAvailable(true);

            port.notifyOnBreakInterrupt(true);

            System.out.println("Add listeners to " + port.getName() + " sucessfully !");

        } catch (TooManyListenersException e) {

            LOGGER.error("There is too many listeners !", e);

        }

    }

TIP

** 一定記得從串口發指令取數據之后加一個延時,等待底層數據傳輸完成再去buffer里面取,不然很大可能數據包不完整。 **


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM