首页 > 编程语言 >java读取com串口

java读取com串口

时间:2024-10-21 11:45:01浏览次数:1  
标签:case SerialPortEvent CommPortIdentifier java 端口 break 串口 com

在用java读取com串口之前,需要引用一个jar包

RXTXcomm.jar

或者用maven(但是maven我试了,好像不行,下载不下来呢)

<dependency>
    <groupId>gnu.io</groupId>
    <artifactId>rxtx</artifactId>
    <version>2.1.7</version>
</dependency>

还有两个dll文件:rxtxParallel.dll、rxtxSerial.dll

复制 rxtxParallel.dll 和 rxtxSerial.dll 到 C:\Program Files\Java\jdk1.8.0_241\jre\bin 下,

串口工具类

方法:

  • openPort打开使用串口
  • serialEvent监听串口事件
  • getPortTypeName根据端口类型获取端口类型名称
  • ComInfo获取所有可用串口
import gnu.io.*;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Enumeration;

class OpenComUtil implements SerialPortEventListener {
    /**
     * 打开端口,注意操作顺序,输入流一定要先获取
     */
    InputStream inputStream = null;

    /**
     * 打开指定的通讯端口。
     *
     * @param comName  需要打开的通讯端口名称。
     * @param port     端口。
     * @param name     应用程序名,用于标识当前打开端口的应用程序。
     * @param baudRate 波特率,即每秒传输的比特数。
     * @param dataBits 数据位个数,通常为5、6、7或8。
     * @param stopBits 停止位个数,通常为1或2。
     * @param parity   校验方式,0代表无奇偶校验,1代表偶校验,2代表奇校验。
     */
    void openPort(String comName, int port, String name, int baudRate, int dataBits, int stopBits, int parity) {
        try {
            /**
             * open方法(应用程序名【随意命名】,阻塞时等待的毫秒数)
             * open方法打开通讯端口,获得一个CommPort对象,它使程序独占端口。
             * 如果端口正被其他应用程序占用,将使用CommPortOwnershipListener事件机制
             * 传递一个PORT_OWNERSHIP_REQUESTED事件。
             * 每个端口都关联一个InputStream和一个OutputStream,如果端口是用
             * open方法打开的,那么任何的getInputStream都将返回相同的数据流对象,除非 有close被调用。
             */
            // open:(应用程序名【随意命名】,阻塞时等待的毫秒数)

            CommPortIdentifier commPortIdentifier = CommPortIdentifier.getPortIdentifier(comName);
            SerialPort serialPort = (SerialPort) commPortIdentifier.open(name, port);
            inputStream = serialPort.getInputStream();
            // 获取输入流

            // 设置串口监听,this对象即本类对象需要继承SerialPortEventListener接口。或者你在这里写一个匿名接口也行。接口内部函数的写法在下面
            serialPort.addEventListener(this);
            // 设置串口数据时间有效(可监听)
            serialPort.notifyOnDataAvailable(true);
            serialPort.notifyOnBreakInterrupt(true);
            // 设置串口通讯参数,可以参考SerialPort类的源码,里面有相关的常量
            // 波特率
            // 数据位个数
            // 停止位
            // 校验方式,0代表无奇偶校验,1代表偶校验,2代表偶校验
            serialPort.setSerialPortParams(baudRate, dataBits, stopBits, parity);
        } catch (PortInUseException e) {
            // 端口正在使用
            throw new RuntimeException(e);
        } catch (Exception e) {
            // 输入输出流错误
            throw new RuntimeException(e);
        }
    }

    /**
     * 监听:处理串口事件。
     *
     * @param event 发生的串口事件,包括通讯中断、溢位错误、帧错误、奇偶校验错误、载波检测、清除发送、数据设备准备好、响铃侦测和输出缓冲区已清空等事件。
     */
    @Override
    public void serialEvent(SerialPortEvent event) {
        switch (event.getEventType()) {
            /**
             * 通讯中断
             */
            case SerialPortEvent.BI: {

            }
            break;
            /**
             * 溢位错误
             */
            case SerialPortEvent.OE: {

            }
            break;
            /**
             * 帧错误
             */
            case SerialPortEvent.FE: {

            }
            break;
            /**
             * 奇偶校验错误
             */
            case SerialPortEvent.PE: {

            }
            break;
            /**
             * 载波检测
             */
            case SerialPortEvent.CD: {

            }
            break;
            /**
             * 清除发送
             */
            case SerialPortEvent.CTS: {

            }
            break;
            /**
             * 数据设备准备好
             */
            case SerialPortEvent.DSR: {

            }
            break;
            /**
             * 响铃侦测
             */
            case SerialPortEvent.RI: {

            }
            break;
            /**
             * 输出缓冲区已清空
             */
            case SerialPortEvent.OUTPUT_BUFFER_EMPTY: {
            }
            break;
            /**
             * 有数据到达
             */
            case SerialPortEvent.DATA_AVAILABLE: {
                // InputStream 通过serialPort在上面的代码中已经获取到了,在这里通过InputStream 读取字节流即可。字节流的操作和咱们一般用法一致
                // 在这里进行读取操作
                byte[] bytes = new byte[1024];
                try {
                    int totalBytesRead = 0;
                    int len = 0;
                    int cardLength = 10;
                    while (totalBytesRead < cardLength) { // 你需要读取的字节数
                        len = inputStream.read(bytes, totalBytesRead, bytes.length - totalBytesRead);
                        if (len == -1) { // 如果读取到流的末尾,跳出循环
                            break;
                        }
                        totalBytesRead += len;
                    }
                    // 检查是否读取到了10位数据
                    if (totalBytesRead >= cardLength) {
                        // 截取前10位数据
                        byte[] cardData = Arrays.copyOfRange(bytes, 0, cardLength);
                        String data = new String(cardData, 0, cardLength, "UTF-8"); // 假设数据是UTF-8编码
                        System.out.println("内容:" + data);
//                        在这里写 处理data的业务逻辑
                    } else {
                        // 处理没有读取到足够数据的情况
                        System.out.println("未能读取到完整的卡数据");
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        inputStream.close(); // 关闭流
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
            break;
            default: {
            }
            break;
        }
    }

    /**
     * 根据端口类型编号获取对应的端口类型名称。
     *
     * @param portType 端口类型的编号,例如:CommPortIdentifier.PORT_I2C、CommPortIdentifier.PORT_PARALLEL等。
     * @return 如果输入的端口类型编号有效,返回对应的端口类型名称;否则返回"unknown type"。
     */
    public static String getPortTypeName(int portType) {
        switch (portType) {
            case CommPortIdentifier.PORT_I2C:
                return "I2C";
            case CommPortIdentifier.PORT_PARALLEL: // 并口
                return "Parallel";
            case CommPortIdentifier.PORT_RAW:
                return "Raw";
            case CommPortIdentifier.PORT_RS485: // RS485端口
                return "RS485";
            case CommPortIdentifier.PORT_SERIAL: // 串口
                return "Serial";
            default:
                return "unknown type";
        }
    }

    /**
     * 获取当前所有可用的串口信息。
     * @return 返回一个字符串,包含所有可用串口的名称和类型。每个串口的信息以换行符分隔。
     */
    public static String ComInfo() {
        String str = "";
        // 获取当前所有可用的串口信息
        Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();
        // 遍历所有的串口信息
        while (portList.hasMoreElements()) {
            // 获取下一个端口信息
            CommPortIdentifier com = (CommPortIdentifier) portList.nextElement();
            // 端口的名称
            String name = com.getName();
            // 端口的类型,需要解析
            int portType = com.getPortType();
            String typeName = getPortTypeName(portType);
            str += "端口名称:" + name + ",端口类型:" + typeName + "\n";

        }
        return str;
    }
}

调用工具类

public class Main {

    public static void main(String[] args) {
            OpenComUtil open = new OpenComUtil();
            open.openPort("COM1",8888,"OpenPortServer",9600,8,1,0);
    }
    
}

标签:case,SerialPortEvent,CommPortIdentifier,java,端口,break,串口,com
From: https://www.cnblogs.com/Gguopeng/p/18489138

相关文章