ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java实现串口通信

2021-03-19 16:01:02  阅读:258  来源: 互联网

标签:Java 通信 serialPort portName 串口 SerialPort logger null


Java实现串口通信

串口通信

所谓串口,指的是串行通信接口(com),区别于并行通信,一次性可传输8位数据,不会发生数据位序混乱,但是比并行通信传输时间长得多,可以双向通信,主要用于设备与设备之间的通信,常用的主要有两类
1.RS232(一对一数据传输,适合本地设备之间的通信)
2.RS485(一对多数据传输,适合远程设备之间的通信)

MODBUS

应用层面的通信协议,Modbus可使用串口和网线(含光纤)方式进行传输

Java实现串口通信

流程:设置串口通信参数—》打开串口—》发送数据—》获得返回的数据—》解析数据—》关闭串口

RXTX串口通信开源框架(JAVA)

     	<dependency>
			<groupId>org.bidib.jbidib.org.qbang.rxtx</groupId>
			<artifactId>rxtxcomm</artifactId>
			<version>2.2</version>
		</dependency>

获取设备可以串口

 Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();

打开指定串口

返回一个可用的SerialPort对象,通过这个对象发送数据,接收数据,关闭串口

1.端口名称,如 COM1,为 null 时,默认使用电脑中能用的端口中的第一个
2.波特率(baudrate),如 9600
3.数据位(datebits),如 SerialPort.DATABITS_8 = 8
4.停止位(stopbits),如 SerialPort.STOPBITS_1 = 1
5.校验位 (parity),如 SerialPort.PARITY_NONE = 0


/**
     * 打开电脑上指定的串口
     *
     * @param portName 端口名称,如 COM1,为 null 时,默认使用电脑中能用的端口中的第一个
     * @param b        波特率(baudrate),如 9600
     * @param d        数据位(datebits),如 SerialPort.DATABITS_8 = 8
     * @param s        停止位(stopbits),如 SerialPort.STOPBITS_1 = 1
     * @param p        校验位 (parity),如 SerialPort.PARITY_NONE = 0
     * @return 打开的串口对象,打开失败时,返回 null
     */
    public static final SerialPort openComPort(String portName, int b, int d, int s, int p) {
        CommPort commPort = null;
        try {
            //当没有传入可用的 com 口时,默认使用电脑中可用的 com 口中的第一个
            if (portName == null || "".equals(portName)) {
                List<String> comPortList = findSystemAllComPort();
                if (comPortList != null && comPortList.size() > 0) {
                    portName = comPortList.get(0);
                }
            }
            logger.info("开始打开串口:portName=" + portName + ",baudrate=" + b + ",datebits=" + d + ",stopbits=" + s + ",parity=" + p);

            //通过端口名称识别指定 COM 端口
            CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
            /**
             * open(String TheOwner, int i):打开端口
             * TheOwner 自定义一个端口名称,随便自定义即可
             * i:打开的端口的超时时间,单位毫秒,超时则抛出异常:PortInUseException if in use.
             * 如果此时串口已经被占用,则抛出异常:gnu.io.PortInUseException: Unknown Application
             */
            commPort = portIdentifier.open(portName, 5000);
            /**
             * 判断端口是不是串口
             * public abstract class SerialPort extends CommPort
             */
            if (commPort instanceof SerialPort) {
                SerialPort serialPort = (SerialPort) commPort;
                /**
                 * 设置串口参数:setSerialPortParams( int b, int d, int s, int p )
                 * b:波特率(baudrate)
                 * d:数据位(datebits),SerialPort 支持 5,6,7,8
                 * s:停止位(stopbits),SerialPort 支持 1,2,3
                 * p:校验位 (parity),SerialPort 支持 0,1,2,3,4
                 * 如果参数设置错误,则抛出异常:gnu.io.UnsupportedCommOperationException: Invalid Parameter
                 * 此时必须关闭串口,否则下次 portIdentifier.open 时会打不开串口,因为已经被占用
                 */
                serialPort.setSerialPortParams(b, d, s, p);
                logger.info("打开串口 " + portName + " 成功...");
                return serialPort;
            } else {
                logger.error("当前端口 " + commPort.getName() + " 不是串口...");
            }
        } catch (NoSuchPortException e) {
            e.printStackTrace();
        } catch (PortInUseException e) {
            logger.warn("串口 " + portName + " 已经被占用,请先解除占用...");
            e.printStackTrace();
        } catch (UnsupportedCommOperationException e) {
            logger.warn("串口参数设置错误,关闭串口,数据位[5-8]、停止位[1-3]、验证位[0-4]...");
            e.printStackTrace();
            if (commPort != null) {//此时必须关闭串口,否则下次 portIdentifier.open 时会打不开串口,因为已经被占用
                commPort.close();
            }
        }
        logger.error("打开串口 " + portName + " 失败...");
        return null;
    }

设置监听

每当事件响应进行对应操作

//设置串口监听
        SerialPortTool.setListenerToSerialPort(serialPort, new SerialPortEventListener() {

            @Override
            public void serialEvent(SerialPortEvent serialPortEvent) {
                switch (serialPortEvent.getEventType()) {
                    case SerialPortEvent.DATA_AVAILABLE: // 1.串口存在有效数据
                        try {
                            //读取串口数据
                            SerialPortTool.readData(serialPort);
                        } catch (Exception e) {
                         }
                        break;

                    case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 2.输出缓冲区已清空
                        logger.error("输出缓冲区已清空");
                        break;

                    case SerialPortEvent.CTS: // 3.清除待发送数据
                        logger.error("清除待发送数据");
                        break;

                    case SerialPortEvent.DSR: // 4.待发送数据准备好了
                        logger.error("待发送数据准备好了");
                        break;

                    case SerialPortEvent.BI: // 10.通讯中断
                        logger.error("与串口设备通讯中断");
                        break;

                    default:
                        break;

                }
            }

        });

往串口中发送数据

serialPort全局对象发送,参数为byte[]数组(16进制)

/**
     * 往串口发送数据
     *
     * @param serialPort 串口对象
     */
    public static void sendDataToComPort(SerialPort serialPort, byte[] orders) {
        OutputStream outputStream = null;
        try {
            if (serialPort != null) {
                outputStream = serialPort.getOutputStream();
                outputStream.write(orders);
                outputStream.flush();
                logger.info("往串口 " + serialPort.getName() + " 发送数据:" + Arrays.toString(orders) + " 完成...");
            } else {
                logger.error("gnu.io.SerialPort 为null,取消数据发送...");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

从串口中读取数据

serialPort全局对象获取

 // 从串口读取数据
    public static byte[] readData(SerialPort serialPort) {
        InputStream is = null;
        byte[] bytes = null;
        try {

            //获得串口的输入流
            is = serialPort.getInputStream();
            // 通过输入流对象的available方法获取数组字节长度
            byte[] readBuffer = new byte[is.available()];
            // 从线路上读取数据流
            int len = 0;
            while ((len = is.read(readBuffer)) != -1) {
                // 直接获取到的数据
                String a=new String(readBuffer, 0, len);
                }
                break;
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            try {
                if (is != null) {
                    is.close();
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return bytes;
    }

关闭串口

 /**
     * 关闭串口
     *
     * @param serialPort 待关闭的串口对象
     */
    public static void closeComPort(SerialPort serialPort) {
        if (serialPort != null) {
            serialPort.close();
            logger.info("关闭串口 " + serialPort.getName());
        }
    }

调试工具(自行百度)

笔记本电脑可以使用usb转串口线,安装转串口驱动就可以使用了
串口

注意

串口占用,连接线断开,中文字符乱码处理(字符超过框架设定的字节,比如中文字符)自行转码,接口文档找厂家要。数据转化为16进制再发送。长时间通信就不用关闭串口

标签:Java,通信,serialPort,portName,串口,SerialPort,logger,null
来源: https://blog.csdn.net/m0_38110240/article/details/115006668

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有