spring boot java JSerialComm 串口 入门开发

参考链接

java串口开发
RXTXcomm与 JSerialComm对比
基本代码

前情提要

JSerialCommRXTXcomm 开发串口不一样, JSerialComm在打开串口发送消息接收消息后必须关闭串口, RXTXcomm 开启一次可继续用, JSerialComm 是独立的。
我在测试的时候,非常纳闷我打开串口了啊,怎么再次调用串口是否打开方法返回的是 false呢,原来只有调用 serialPort.openPort(1000) 方法 ,serialPort.isOpen() 才会返回 true, 必须调用一次打开一次, 关闭一次。不然下次就无法打开了。

调试工具

usr-tcp232 软件

demo示例地址

代码

导入依赖

这里 <version>[2.0.0,3.0.0)</version> 会默认导入最新的版本

<!--串口开发依赖-->
<dependency>
    <groupId>com.fazecast</groupId>
    <artifactId>jSerialComm</artifactId>
    <version>[2.0.0,3.0.0)</version>
</dependency> 


 <!--其他工具类依赖 -->
<dependency>
   <groupId>com.google.guava</groupId>
   <artifactId>guava</artifactId>
   <version>31.1-jre</version>
</dependency>

<dependency>
   <groupId>com.alibaba.fastjson2</groupId>
   <artifactId>fastjson2</artifactId>
   <version>2.0.26</version>
</dependency>

<dependency>
   <groupId>cn.hutool</groupId>
   <artifactId>hutool-all</artifactId>
   <version>5.8.18</version>
</dependency>

工具类集测试

工具类

/**
 * 串口存在有效数据监听
 */
public interface DataAvailableListener {
    /**
     * 串口存在有效数据
     */
    void dataAvailable();
}

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

    private final DataAvailableListener mDataAvailableListener;

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

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

    /**
     * 系列活动
     *
     * @param serialPortEvent 串口事件
     */
    @Override
    public void serialEvent(SerialPortEvent serialPortEvent) {
        if (mDataAvailableListener != null) {
            mDataAvailableListener.dataAvailable();
        }
    }
}
package com.example.rxtxdemo.rxtx;

import com.fazecast.jSerialComm.SerialPort;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
public class SerialPortManager {


    /**
     * 查找所有可用端口
     *
     * @return {@link List}<{@link String}>
     */
    public static List<String> findPorts() {
        // 获得当前所有可用串口
        SerialPort[] serialPorts = SerialPort.getCommPorts();
        List<String> portNameList = Lists.newLinkedList();
        // 将可用串口名添加到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);
        if (null != baudRate) {
            serialPort.setComPortParameters(baudRate, 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) {
        log.info("开始发送消息====》 {}", serialPort.bytesAvailable());
        byte[] reslutData = 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) {
                reslutData = readBuffer;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return reslutData;
    }

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

测试类

package com.example.rxtxdemo.rxtx;

import cn.hutool.core.util.HexUtil;
import com.alibaba.fastjson2.JSONObject;
import com.fazecast.jSerialComm.SerialPort;
import com.google.common.collect.Maps;
import gnu.io.PortInUseException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;

@Slf4j
@RestController
@RequiredArgsConstructor
public class RxtxRest {



 @GetMapping("sendData")
 public Map<String, Object> sendData(@RequestParam String portName,  @RequestParam Integer baudRate, @RequestParam String content) {
     Map<String, Object> map = Maps.newHashMap();
     SerialPort serialPort = SerialPortManager.openPort(portName, baudRate);
     byte[] bytes = HexUtil.decodeHex(content);
     try {
         SerialPortManager.sendToPort(serialPort, bytes);
         Thread.sleep(1000);
         byte[] bytes1 = SerialPortManager.readFromPort(serialPort);
         String receiveMsg = HexUtil.encodeHexStr(bytes1, false);
         map.put("msg", receiveMsg);
     } catch (InterruptedException e) {
         e.printStackTrace();
     }
     SerialPortManager.closePort(serialPort);
     return map;
 }




 @GetMapping("ports")
 public Map<String, Object> test() {
     Map<String, Object> map = Maps.newHashMap();
     List<String> ports = SerialPortManager.findPorts();
     ports.forEach(port -> map.put(port, SerialPort.getCommPort(port).isOpen()));
     return map;
 }





   


@GetMapping("test1")
public void test1() {
    SerialPort[] serialPorts = SerialPort.getCommPorts();
    //查找所有串口
    for(SerialPort serialPort: serialPorts){
        //打印串口名称,如COM4
        System.out.println("Port:"+serialPort.getSystemPortName());
        //打印串口类型,如USB Serial
        System.out.println("PortDesc:"+serialPort.getPortDescription());
        //打印串口的完整类型,如USB-SERIAL CH340(COM4)
        System.out.println("PortDesc:"+serialPort.getDescriptivePortName());
        //获取到第一个串口
        //设置波特率为112500
        serialPort.setBaudRate(112500);
        //设置超时
        serialPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING | SerialPort.TIMEOUT_WRITE_BLOCKING, 1000, 1000);
        serialPort.setRTS();//设置RTS。也可以设置DTR
        //设置串口的控制流,可以设置为disabled,或者CTS, RTS/CTS, DSR, DTR/DSR, Xon, Xoff, Xon/Xoff等
        serialPort.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED);
        //一次性设置所有的串口参数,第一个参数为波特率,默认9600;第二个参数为每一位的大小,默认8,可以输入5到8之间的值;第三个参数为停止位大小,只接受内置常量,可以选择(ONE_STOP_BIT, ONE_POINT_FIVE_STOP_BITS, TWO_STOP_BITS);第四位为校验位,同样只接受内置常量,可以选择 NO_PARITY, EVEN_PARITY, ODD_PARITY, MARK_PARITY,SPACE_PARITY。
        serialPort.setComPortParameters(112500, 8, SerialPort.ONE_STOP_BIT, SerialPort.NO_PARITY);
        if(!serialPort.isOpen()){
            //判断串口是否打开,如果没打开,就打开串口。打开串口的函数会返回一个boolean值,用于表明串口是否成功打开了
            boolean openFlag = serialPort.openPort();
            log.info("打开串口  == {}", openFlag);
        }
        //关闭串口。该函数同样会返回一个boolean值,表明串口是否成功关闭
        boolean closeFlag = serialPort.closePort();
        log.info("关闭== {}", closeFlag);
    }
}

测试

调用 ip:port/sendData?portName=COM3&baudRate=1200&content=msg 查看返回信息是否跟调试软件一致即可

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值