JAVA的jSerialComm类库和串口协议通信案例

前言

本文旨在介绍JAVA的jSerialComm类库和串口协议通信案例。

依赖

<!--jSerialComm-->
<dependency>
    <groupId>com.fazecast</groupId>
    <artifactId>jSerialComm</artifactId>
    <version>2.6.2</version>
</dependency>

SerialPortManager

@Slf4j
@Component
public class SerialPortManager {

    // 查找所有可用端口
    public static List<String> findPorts() {
        // 获得当前所有可用串口
        SerialPort[] serialPorts = SerialPort.getCommPorts();
        List<String> portNameList = new ArrayList<>();
        // 将可用串口名添加到List并返回该List
        for (SerialPort serialPort : serialPorts) {
            portNameList.add(serialPort.getSystemPortName());
        }
        // 去重
        portNameList = portNameList.stream().distinct().collect(Collectors.toList());
        return portNameList;
    }

    /**
     * 打开串口
     *
     * @param portName 端口名称
     * @param baudRate 波特率
     * @return 串口对象
     */
    public static SerialPort openPort(String portName, Integer baudRate) {
        SerialPort serialPort = SerialPort.getCommPort(portName);
        if (baudRate != null) {
            serialPort.setBaudRate(baudRate);
        }
        // 开启串口
        if (!serialPort.isOpen()) {
            serialPort.openPort(1000);
        } else {
            return serialPort;
        }
        // 设置一下串口的波特率等参数
        // 数据位:8
        // 停止位:1
        // 校验位:None
        serialPort.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED);
        serialPort.setComPortParameters(Optional.ofNullable(baudRate).orElse(9600), 8, SerialPort.ONE_STOP_BIT, SerialPort.NO_PARITY);
        serialPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING | SerialPort.TIMEOUT_WRITE_BLOCKING, 1000, 1000);
        return serialPort;
    }

    /**
     * 关闭串口
     *
     * @param serialPort 待关闭的串口对象
     */
    public static void closePort(SerialPort serialPort) {
        if (serialPort != null && serialPort.isOpen()) {
            serialPort.closePort();
        }
    }

    /**
     * 往串口发送数据
     *
     * @param serialPort 串口对象
     * @param content    待发送数据
     */
    public static void sendToPort(SerialPort serialPort, byte[] content) {
        if (!serialPort.isOpen()) {
            return;
        }
        serialPort.writeBytes(content, content.length);
    }

    /**
     * 从串口读取数据
     *
     * @param serialPort 当前已建立连接的SerialPort对象
     * @return 读取到的数据
     */
    public static byte[] readFromPort(SerialPort serialPort) {
        byte[] resultData = null;
        try {
            if (!serialPort.isOpen()) {
                return null;
            }
            int i = 0;
            while (serialPort.bytesAvailable() > 0 && i++ < 5) Thread.sleep(20);
            byte[] readBuffer = new byte[serialPort.bytesAvailable()];
            int numRead = serialPort.readBytes(readBuffer, readBuffer.length);
            if (numRead > 0) {
                resultData = readBuffer;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return resultData;
    }

    /**
     * 添加监听器
     *
     * @param serialPort 串口对象
     * @param listener   串口存在有效数据监听
     */
    public static void addListener(SerialPort serialPort, DataAvailableListener listener) {
        try {
            // 给串口添加监听器
            serialPort.addDataListener(new SerialPortListener(listener));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

SerialPortListener

/**
 * 串口监听
 */
@Slf4j
@Component
public class SerialPortListener implements SerialPortDataListener {

    private DataAvailableListener mDataAvailableListener;

    public SerialPortListener() {
    }

    public SerialPortListener(DataAvailableListener mDataAvailableListener) {
        this.mDataAvailableListener = mDataAvailableListener;
    }

    @Override
    public int getListeningEvents() {
        // 必须是return这个才会开启串口工具的监听
        return SerialPort.LISTENING_EVENT_DATA_AVAILABLE;
    }

    public void serialEvent(SerialPortEvent serialPortEvent) {
        if (mDataAvailableListener != null) {
            mDataAvailableListener.dataAvailable();
        }
    }
}

DataAvailableListener

/**
 * 数据监听
 */
public interface DataAvailableListener {

    /**
     * 存在有效数据
     */
    void dataAvailable();
}

串口监听器SerialStarter

@Component
@Slf4j
public class SerialStarter {

    /**
     * 静态串口对象:类加载时打开一次,全局共用
     */
    private static final SerialPort serialPort;

    static {
        serialPort = SerialPortManager.openPort("COM2", 115200);
        if (serialPort.isOpen()) {
            log.info("serial串口已打开");
        } else {
            log.error("serial串口打开失败");
        }
    }

    @PostConstruct
    public void addListener() {
        if (!serialPort.isOpen()) {
            return;
        }
        // 给当前串口设置监听器
        SerialPortManager.addListener(serialPort, new DataAvailableListener() {
            @Override
            public void dataAvailable() {
                // 监听到的串口返回数据
                byte[] back = SerialPortManager.readFromPort(serialPort);
                if (back == null) {
                    return;
                }
                String backStr = new String(back, StandardCharsets.UTF_8);
                log.info("串口返回数据,{}", backStr);
            }
        });
    }

    /**
     * 发送数据
     *
     * @param message 消息
     */
    public static void sendData(String message) {
        if (serialPort == null || !serialPort.isOpen()) {
            throw new RuntimeException("serial串口未打开");
        }
        byte[] content = message.getBytes();
        SerialPortManager.sendToPort(serialPort, content);
    }
}

测试

工具

  • vspd

1

java项目是springboot工程,即启动项目。

2

3

  • sscom

4

5

测试过程

  • 从站到主站

6

  • 主站到从站

    @RestController
    @RequestMapping("/serial")
    public class SendMessageController {
    
        @PostMapping("/send")
        public void sendMessage(@RequestParam String message) {
            SerialStarter.sendData(message);
        }
    }
    

    发送http请求。
    7

posted @ 2026-08-19 16:14  南翔技校毕业后  阅读(2)  评论(0)    收藏  举报