首页 > 编程语言 >Java利用Rxtx进行串口通讯

Java利用Rxtx进行串口通讯

时间:2023-07-30 17:03:51浏览次数:28  
标签:case Java Rxtx SerialPort SerialPortEvent 串口 portName return

最近在做传感器数据采集的工作,底层是基于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里面取,不然很大可能数据包不完整。 **

标签:case,Java,Rxtx,SerialPort,SerialPortEvent,串口,portName,return
From: https://blog.51cto.com/u_16209821/6901383

相关文章

  • java基础上(笔记)
    变量变量:程序运行过程中,其值可以发生改变的量。变量由三部分组成:变量名、变量值、数据类型。格式:数据类型变量名=变量值;如:inta=10;(定义变量)变量的使用:取值与修改值。取值格式:变量名修改格式:变量名=变量值;注意事项:不能定义已存在的变量;不能使用未定义的变量;整数默认最大......
  • Java概述
    第一章·内容介绍......
  • JavaScript学习 -- 对称加密算法DES
    在现代的互联网时代,数据安全性备受关注。为了保护敏感数据的机密性,对称加密算法是一种常用的方法。在JavaScript中,DES(DataEncryptionStandard)是一种常用的对称加密算法。本篇博客将为您展示如何在JavaScript中使用DES算法进行加密和解密,并提供一个实际的例子。首先,我们需要使用Cr......
  • java学习前须知(笔记)
    Path环境变量的配置我的电脑单击右键选择属性,就进入了设置的关于选项,找到高级系统设置,高级里面选环境变量,弹出窗口里面选系统变量下的新建,取名JAVA_HOME;路径选为jdk-8的根目录,即可得到一个系统变量;选中系统变量里的Path,编辑即可,可新建%JAVA_HOME%\bin,这样就可以直接在cmd里启......
  • Java概述
    第一章·内容介绍......
  • Java学习-4.数组
    一、数组类型数组是存储多个变量(元素)的东西(容器),这多个变量的数据类型要一致。定义一个数组类型的变量,使用数组类型“类型[]”,例如,int[]。和单个基本类型变量不同,数组变量初始化必须使用newint[5]表示创建一个可容纳5个int元素的数组。Java的数组有几个特点:数组所有元素......
  • 在同一个Java进程中连接多个RocketMQ集群
     RocketMQ使用场景:作为消费者:用户应用-->MQ集群A-->权益应用消息内容:客户开户/销户相关消息作为生产者:权益应用-->MQ集群B-->信贷应用消息内容:卡券事件消息问题现象:一个Java进程要连接多个RocketMQ集群时,作为消费者功能无法正常使用,作为生产者功能可以正常使用......
  • MAC中Java实现多版本JDK并存并随时切换的解决方案
    编辑SHELL配置文件,新版macOS默认使用的是zsh,打开终端,编辑zsh的配置文件.zshrcvi.zshrc在配置文件的末尾添加下面的内容:#>>>Java多版本共存exportJAVA_11_HOME=`/usr/libexec/java_home-v11`exportJAVA_17_HOME=`/usr/libexec/java_home-v17`#defaultJavaversi......
  • java使用线程池实现接口自动化中的并发测试
    importjava.util.concurrent.ExecutionException;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.Future;publicvoidtest()throwsExecutionException,InterruptedException{ExecutorServ......
  • Java之Stream流的收集
    Java之Stream流的收集收集Stream流的含义:就是把Stream流操作后的结果数据转到集合或者数组中去。Stream流只是方便操作集合/数组的手段。集合/数组才是开发中的目的。Stream流的收集方法名称说明Rcollect(Collectorcollector)开始收集Stream流,指定收集器Col......