RXTX實(shí)現(xiàn)JAVA串口編程

? ? ? ?給大家分項(xiàng)下用RXTX庫(kù)實(shí)現(xiàn)JAVA串口編程。

一 準(zhǔn)備工作

1.1 下載資源文件

? ? ? ?首先下載RXTX庫(kù)對(duì)應(yīng)的資源文件。下載地址 http://fizzed.com/oss/rxtx-for-java 大家根據(jù)自己的系統(tǒng)下載對(duì)應(yīng)的文件。

RXTX-FOR-JAVA.png
  • Windows-x64 對(duì)應(yīng)windows 64位系統(tǒng)。
  • Windows-x86 對(duì)應(yīng)windows 32位系統(tǒng)。
  • Windows-ia64 這種用的比較少,我們不管。
  • Linux-x86_64 對(duì)應(yīng)Linux 64位系統(tǒng)。
  • Linux-i386 對(duì)應(yīng)Linux 32位系統(tǒng)。

? ? ? ?每個(gè)文件下面都有我們下面需要的所有文件。

1.1 拷貝動(dòng)態(tài)庫(kù)

? ? ? ?RXJX的實(shí)現(xiàn)還需要依賴幾個(gè)動(dòng)態(tài)庫(kù),所以我們要先把動(dòng)態(tài)庫(kù)放到對(duì)應(yīng)的jdk目錄下面去。window和linux拷貝的文件不同,如下所示:

window平臺(tái):

  • 拷貝 rxtxSerial.dll —> <JAVA_HOME>\jre\bin
  • 拷貝 rxtxParallel.dll —> <JAVA_HOME>\jre\bin

linux平臺(tái):

  • 拷貝 librxtxSerial.so —> <JAVA_HOME>/jre/lib/i386/
  • 拷貝 librxtxParallel.so —> <JAVA_HOME>/jre/lib/i386/

1.2 項(xiàng)目引入RXTXcomm.jar

? ? ? ?RXTXcomm.jar文件引入到工程代碼里面去。

? ? ? ?比如我們把RXTXcomm.jar文件放到工程目錄下resource/jar目錄下面去。然后在pom.xml中把RXTXcomm.jar引入進(jìn)來(lái)。

        <!-- 串口jar -->
        <dependency>
            <groupId>gnu.io</groupId>
            <artifactId>com-lib</artifactId>
            <version>2.2</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/resources/jar/RXTXcomm.jar</systemPath>
        </dependency>

二 實(shí)現(xiàn)代碼

? ? ? ?前面準(zhǔn)備工作做好了,接下來(lái)就是代碼實(shí)現(xiàn),好多代碼咱們也是從網(wǎng)上copy過(guò)來(lái)的,這里我就直接貼代碼了。

2.1 串口參數(shù)的簡(jiǎn)單封裝

package com.pilot.ioserver.basic.pbl.port.serialPort;

import gnu.io.SerialPort;

/**
 * @name: SerialPortParameter
 * @author: tuacy.
 * @date: 2019/6/26.
 * @version: 1.0
 * @Description: 串口參數(shù)
 */
public final class SerialPortParameter {

    /**
     * 串口名稱(COM0、COM1、COM2等等)
     */
    private String serialPortName;
    /**
     * 波特率
     * 默認(rèn):115200
     */
    private int baudRate;
    /**
     * 數(shù)據(jù)位 默認(rèn)8位
     * 可以設(shè)置的值:SerialPort.DATABITS_5、SerialPort.DATABITS_6、SerialPort.DATABITS_7、SerialPort.DATABITS_8
     * 默認(rèn):SerialPort.DATABITS_8
     */
    private int dataBits;
    /**
     * 停止位
     * 可以設(shè)置的值:SerialPort.STOPBITS_1、SerialPort.STOPBITS_2、SerialPort.STOPBITS_1_5
     * 默認(rèn):SerialPort.STOPBITS_1
     */
    private int stopBits;
    /**
     * 校驗(yàn)位
     * 可以設(shè)置的值:SerialPort.PARITY_NONE、SerialPort.PARITY_ODD、SerialPort.PARITY_EVEN、SerialPort.PARITY_MARK、SerialPort.PARITY_SPACE
     * 默認(rèn):SerialPort.PARITY_NONE
     */
    private int parity;

    public SerialPortParameter(String serialPortName) {
        this.serialPortName = serialPortName;
        this.baudRate = 115200;
        this.dataBits = SerialPort.DATABITS_8;
        this.stopBits = SerialPort.STOPBITS_1;
        this.parity = SerialPort.PARITY_NONE;
    }

    public SerialPortParameter(String serialPortName, int baudRate) {
        this.serialPortName = serialPortName;
        this.baudRate = baudRate;
        this.dataBits = SerialPort.DATABITS_8;
        this.stopBits = SerialPort.STOPBITS_1;
        this.parity = SerialPort.PARITY_NONE;
    }

    public String getSerialPortName() {
        return serialPortName;
    }

    public void setSerialPortName(String serialPortName) {
        this.serialPortName = serialPortName;
    }

    public int getBaudRate() {
        return baudRate;
    }

    public void setBaudRate(int baudRate) {
        this.baudRate = baudRate;
    }

    public int getDataBits() {
        return dataBits;
    }

    public void setDataBits(int dataBits) {
        this.dataBits = dataBits;
    }

    public int getStopBits() {
        return stopBits;
    }

    public void setStopBits(int stopBits) {
        this.stopBits = stopBits;
    }

    public int getParity() {
        return parity;
    }

    public void setParity(int parity) {
        this.parity = parity;
    }
}

2.2 串口工具類的簡(jiǎn)單封裝

package com.pilot.ioserver.basic.pbl.port.serialPort;

import gnu.io.*;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.TooManyListenersException;

/**
 * @name: SerialPortUtil
 * @author: tuacy.
 * @date: 2019/6/26.
 * @version: 1.0
 * @Description: 串口工具類
 */
public class SerialPortUtil {

    /**
     * 獲得系統(tǒng)可用的端口名稱列表(COM0、COM1、COM2等等)
     *
     * @return List<String>可用端口名稱列表
     */

    @SuppressWarnings("unchecked")
    public static List<String> getSerialPortList() {
        List<String> systemPorts = new ArrayList<>();
        //獲得系統(tǒng)可用的端口
        Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();
        while (portList.hasMoreElements()) {
            String portName = portList.nextElement().getName();//獲得端口的名字
            systemPorts.add(portName);
        }
        return systemPorts;
    }

    /**
     * 打開串口
     *
     * @param serialPortName 串口名稱
     * @return SerialPort 串口對(duì)象
     * @throws NoSuchPortException               對(duì)應(yīng)串口不存在
     * @throws PortInUseException                串口在使用中
     * @throws UnsupportedCommOperationException 不支持操作操作
     */
    public static SerialPort openSerialPort(String serialPortName)
            throws NoSuchPortException, PortInUseException, UnsupportedCommOperationException {
        SerialPortParameter parameter = new SerialPortParameter(serialPortName);
        return openSerialPort(parameter);
    }

    /**
     * 打開串口
     *
     * @param serialPortName 串口名稱
     * @param baudRate       波特率
     * @return SerialPort 串口對(duì)象
     * @throws NoSuchPortException               對(duì)應(yīng)串口不存在
     * @throws PortInUseException                串口在使用中
     * @throws UnsupportedCommOperationException 不支持操作操作
     */
    public static SerialPort openSerialPort(String serialPortName, int baudRate)
            throws NoSuchPortException, PortInUseException, UnsupportedCommOperationException {
        SerialPortParameter parameter = new SerialPortParameter(serialPortName, baudRate);
        return openSerialPort(parameter);
    }

    /**
     * 打開串口
     *
     * @param serialPortName 串口名稱
     * @param baudRate       波特率
     * @param timeout        串口打開超時(shí)時(shí)間
     * @return SerialPort 串口對(duì)象
     * @throws NoSuchPortException               對(duì)應(yīng)串口不存在
     * @throws PortInUseException                串口在使用中
     * @throws UnsupportedCommOperationException 不支持操作操作
     */
    public static SerialPort openSerialPort(String serialPortName, int baudRate, int timeout)
            throws NoSuchPortException, PortInUseException, UnsupportedCommOperationException {
        SerialPortParameter parameter = new SerialPortParameter(serialPortName, baudRate);
        return openSerialPort(parameter, timeout);
    }

    /**
     * 打開串口
     *
     * @param parameter 串口參數(shù)
     * @return SerialPort 串口對(duì)象
     * @throws NoSuchPortException               對(duì)應(yīng)串口不存在
     * @throws PortInUseException                串口在使用中
     * @throws UnsupportedCommOperationException 不支持操作操作
     */
    public static SerialPort openSerialPort(SerialPortParameter parameter)
            throws NoSuchPortException, PortInUseException, UnsupportedCommOperationException {
        return openSerialPort(parameter, 2000);
    }

    /**
     * 打開串口
     *
     * @param parameter 串口參數(shù)
     * @param timeout   串口打開超時(shí)時(shí)間
     * @return SerialPort串口對(duì)象
     * @throws NoSuchPortException               對(duì)應(yīng)串口不存在
     * @throws PortInUseException                串口在使用中
     * @throws UnsupportedCommOperationException 不支持操作操作
     */
    public static SerialPort openSerialPort(SerialPortParameter parameter, int timeout)
            throws NoSuchPortException, PortInUseException, UnsupportedCommOperationException {
        //通過(guò)端口名稱得到端口
        CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(parameter.getSerialPortName());
        //打開端口,(自定義名字,打開超時(shí)時(shí)間)
        CommPort commPort = portIdentifier.open(parameter.getSerialPortName(), timeout);
        //判斷是不是串口
        if (commPort instanceof SerialPort) {
            SerialPort serialPort = (SerialPort) commPort;
            //設(shè)置串口參數(shù)(波特率,數(shù)據(jù)位8,停止位1,校驗(yàn)位無(wú))
            serialPort.setSerialPortParams(parameter.getBaudRate(), parameter.getDataBits(), parameter.getStopBits(), parameter.getParity());
            System.out.println("開啟串口成功,串口名稱:" + parameter.getSerialPortName());
            return serialPort;
        } else {
            //是其他類型的端口
            throw new NoSuchPortException();
        }
    }


    /**
     * 關(guān)閉串口
     *
     * @param serialPort 要關(guān)閉的串口對(duì)象
     */
    public static void closeSerialPort(SerialPort serialPort) {
        if (serialPort != null) {
            serialPort.close();
            System.out.println("關(guān)閉了串口:" + serialPort.getName());
        }
    }

    /**
     * 向串口發(fā)送數(shù)據(jù)
     *
     * @param serialPort 串口對(duì)象
     * @param data       發(fā)送的數(shù)據(jù)
     */
    public static void sendData(SerialPort serialPort, byte[] data) {
        OutputStream os = null;
        try {
            //獲得串口的輸出流
            os = serialPort.getOutputStream();
            os.write(data);
            os.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 從串口讀取數(shù)據(jù)
     *
     * @param serialPort 要讀取的串口
     * @return 讀取的數(shù)據(jù)
     */
    public static byte[] readData(SerialPort serialPort) {
        InputStream is = null;
        byte[] bytes = null;
        try {
            //獲得串口的輸入流
            is = serialPort.getInputStream();
            //獲得數(shù)據(jù)長(zhǎng)度
            int bufflenth = is.available();
            while (bufflenth != 0) {
                //初始化byte數(shù)組
                bytes = new byte[bufflenth];
                is.read(bytes);
                bufflenth = is.available();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return bytes;
    }

    /**
     * 給串口設(shè)置監(jiān)聽(tīng)
     *
     * @param serialPort serialPort 要讀取的串口
     * @param listener   SerialPortEventListener監(jiān)聽(tīng)對(duì)象
     * @throws TooManyListenersException 監(jiān)聽(tīng)對(duì)象太多
     */
    public static void setListenerToSerialPort(SerialPort serialPort, SerialPortEventListener listener) throws TooManyListenersException {
        //給串口添加事件監(jiān)聽(tīng)
        serialPort.addEventListener(listener);
        //串口有數(shù)據(jù)監(jiān)聽(tīng)
        serialPort.notifyOnDataAvailable(true);
        //中斷事件監(jiān)聽(tīng)
        serialPort.notifyOnBreakInterrupt(true);
    }


}

2.3 測(cè)試類

? ? ? ?我們簡(jiǎn)單的寫一個(gè)單元測(cè)試類

package com.pilot.ioserver.basic.pbl.port.serialPort;

import gnu.io.*;
import org.junit.Test;

import java.util.List;
import java.util.TooManyListenersException;

/**
 * @name: SerialPortUtilTest
 * @author: tuacy.
 * @date: 2019/6/26.
 * @version: 1.0
 * @Description: 串口測(cè)試代碼
 */
public class SerialPortUtilTest {

    /**
     * 測(cè)試獲取串口列表
     */
    @Test
    public void getSystemPortList() {

        List<String> portList = SerialPortUtil.getSerialPortList();
        System.out.println(portList);

    }

    /**
     * 測(cè)試串口打開,讀,寫操作
     */
    @Test
    public void serialPortAction() {
        try {
            final SerialPort serialPort = SerialPortUtil.openSerialPort("COM2", 115200);
            //啟動(dòng)一個(gè)線程每2s向串口發(fā)送數(shù)據(jù),發(fā)送1000次hello
            new Thread(() -> {
                int i = 1;
                while (i < 1000) {
                    String s = "hello";
                    byte[] bytes = s.getBytes();
                    SerialPortUtil.sendData(serialPort, bytes);//發(fā)送數(shù)據(jù)
                    i++;
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
            //設(shè)置串口的listener
            SerialPortUtil.setListenerToSerialPort(serialPort, event -> {
                //數(shù)據(jù)通知
                if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
                    byte[] bytes = SerialPortUtil.readData(serialPort);
                    System.out.println("收到的數(shù)據(jù)長(zhǎng)度:" + bytes.length);
                    System.out.println("收到的數(shù)據(jù):" + new String(bytes));
                }
            });
            try {
                // sleep 一段時(shí)間保證線程可以執(zhí)行完
                Thread.sleep(3 * 30 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } catch (NoSuchPortException | PortInUseException | UnsupportedCommOperationException | TooManyListenersException e) {
            e.printStackTrace();
        }
    }

}

三 測(cè)試

? ? ? ?代碼寫完了,接下來(lái)就是驗(yàn)證了。我是在window條件下驗(yàn)證測(cè)試的,也在網(wǎng)上找了兩個(gè)工具,一個(gè)模擬串口工具,一個(gè)串口命令工具。為了方便大家我們把這兩個(gè)工具放一起又重新上傳在csdn上了。下載地址 https://download.csdn.net/download/wuyuxing24/11260170

3.1 虛擬串口

? ? ? ? 使用虛擬串口工具,虛擬兩個(gè)串口。比如這里我們虛擬了COM1和COM2出來(lái)。

虛擬串口工具.png

3.2 運(yùn)行單元測(cè)試代碼

? ? ? ? 運(yùn)行我們上面編寫的測(cè)試代碼(測(cè)試代碼我們連接COM2)。同時(shí)啟動(dòng)串口調(diào)試工具,測(cè)試下串口的收發(fā)。

串口

? ? ? ?這樣我們就用RXTX簡(jiǎn)單的實(shí)現(xiàn)了串口的收發(fā)邏輯。其他更加高級(jí)的用法大家可以去看看RXTX的文檔。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容