java串口接收和发送消息集成Springboot

写在前面:1、jdk我用的1.8.0_31 ,不能用太高的java版本。

2、(1)将rxtxParallel.dll和rxtxSerial.dll文件放到${JAVA_HOME}(jdk目录,不是jre目录)\jre\bin目录下

如: C:\Program Files\Java\jdk1.8.0_31\jre\bin
      (2)、将RXTXcomm.jar 包放到{JAVA_HOME}jdk目录\jre\lib\ext目录下即可 

如:  C:\Program Files\Java\jdk1.8.0_31\jre\lib\ext

dll和jar包传送门: 

链接:https://pan.baidu.com/s/1cdMxM-x1P6TWmZgPNuoFIQ 
提取码:afva

StartService 跟项目启动类一起启动。初始化一个串口,并监听串口是否接收到数据。
import com.hs.reader3.config.ParamConfig;
import com.hs.reader3.config.SerialPortUtils;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Order(value = 2)
public class StartService implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        SerialPortUtils spu = new SerialPortUtils();
        ParamConfig paramConfig = new ParamConfig("COM5", 9600, 0, 8, 1);
        //初始化串口
        spu.init(paramConfig);
        System.out.println("初始化com串口结束...,使用" + paramConfig.getSerialNumber());
    }
}
ParamConfig 配置类


public class ParamConfig {
    private String serialNumber;// 串口号
    private int baudRate;       // 波特率
    private int checkoutBit;    // 校验位
    private int dataBit;        // 数据位
    private int stopBit;        // 停止位

    public ParamConfig() {}

    /**
     * 构造方法
     * @param serialNumber    串口号
     * @param baudRate        波特率
     * @param checkoutBit    校验位
     * @param dataBit        数据位
     * @param stopBit        停止位
     */
    public ParamConfig(String serialNumber, int baudRate, int checkoutBit, int dataBit, int stopBit) {
        this.serialNumber = serialNumber;
        this.baudRate = baudRate;
        this.checkoutBit = checkoutBit;
        this.dataBit = dataBit;
        this.stopBit = stopBit;
    }

    public String getSerialNumber() {
        return serialNumber;
    }

    public void setSerialNumber(String serialNumber) {
        this.serialNumber = serialNumber;
    }

    public int getBaudRate() {
        return baudRate;
    }

    public void setBaudRate(int baudRate) {
        this.baudRate = baudRate;
    }

    public int getCheckoutBit() {
        return checkoutBit;
    }

    public void setCheckoutBit(int checkoutBit) {
        this.checkoutBit = checkoutBit;
    }

    public int getDataBit() {
        return dataBit;
    }

    public void setDataBit(int dataBit) {
        this.dataBit = dataBit;
    }

    public int getStopBit() {
        return stopBit;
    }

    public void setStopBit(int stopBit) {
        this.stopBit = stopBit;
    }

}
SerialPortUtils 核心业务类:实现接收和发送

import com.hs.reader3.dao.DetectionRlEjrlMapper;
import com.hs.reader3.entity.DetectionRlEjrl;
import com.hs.reader3.until.StringUtilss;
import gnu.io.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.TooManyListenersException;

@Slf4j
@Component
public  class SerialPortUtils implements SerialPortEventListener {


    // 检测系统中可用的通讯端口类
    private static CommPortIdentifier commPortId;
    // 枚举类型
    private static Enumeration<CommPortIdentifier> portList;
    // RS232串口
    private static SerialPort serialPort;
    // 输入流
    private static InputStream inputStream;
    // 输出流
    private static OutputStream outputStream;
    // 保存串口返回信息
    private String data;
    // 保存串口返回信息十六进制
    private String dataHex;

    public SerialPortUtils() {
    }

    private static DetectionRlEjrlMapper detectionRlEjrlMapper;
    @Autowired
    DetectionRlEjrlMapper detectionRlEjrlMapper0;

    @PostConstruct
    private void detectionRlEjrlMapper(){
        this.detectionRlEjrlMapper = detectionRlEjrlMapper0;
    }
    /**
     * 初始化串口
     *
     * @throws
     * @Author Jarvis
     * @param: paramConfig  存放串口连接必要参数的对象(会在下方给出类代码)
     * @return: void
     */
    @SuppressWarnings("unchecked")
    public void init(ParamConfig paramConfig) {
        // 获取系统中所有的通讯端口
        portList = CommPortIdentifier.getPortIdentifiers();
        System.out.println("所有串口:" + portList.toString());
        // 记录是否含有指定串口
        boolean isExsist = false;
        // 循环通讯端口
        while (portList.hasMoreElements()) {
            commPortId = portList.nextElement();
            System.out.println(commPortId.getName());
            // 判断是否是串口
            if (commPortId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
                // 比较串口名称是否是指定串口
                if (paramConfig.getSerialNumber().equals(commPortId.getName())) {
                    // 串口存在
                    isExsist = true;
                    // 打开串口
                    try {
                        // open:(应用程序名【随意命名】,阻塞时等待的毫秒数)
//                        serialPort = (SerialPort) commPortId.open(Object.class.getSimpleName(), 2000);
                        serialPort = (SerialPort) commPortId.open("COM5", 2000);
                        // 设置串口监听
                        serialPort.addEventListener(this);
                        // 设置串口数据时间有效(可监听)
                        serialPort.notifyOnDataAvailable(true);
                        // 设置串口通讯参数:波特率,数据位,停止位,校验方式
                        serialPort.setSerialPortParams(paramConfig.getBaudRate(), paramConfig.getDataBit(),
                                paramConfig.getStopBit(), paramConfig.getCheckoutBit());
                    } catch (PortInUseException e) {
                        e.printStackTrace();
                    } catch (TooManyListenersException e) {
                        e.printStackTrace();
                    } catch (UnsupportedCommOperationException e) {
                        e.printStackTrace();
                    }
                    // 结束循环
                    break;
                }
            }
        }
        // 若不存在该串口则抛出异常
        if (!isExsist) {
            new NoSuchPortException();

        }
    }

    /**
     * 实现接口SerialPortEventListener中的方法 读取从串口中接收的数据
     */
    @Override
    public void serialEvent(SerialPortEvent event) {
        switch (event.getEventType()) {
            case SerialPortEvent.BI: // 通讯中断
                System.out.println("event = 通讯中断");
                break;
            case SerialPortEvent.OE: // 溢位错误
            case SerialPortEvent.FE: // 帧错误
            case SerialPortEvent.PE: // 奇偶校验错误
            case SerialPortEvent.CD: // 载波检测
            case SerialPortEvent.CTS: // 清除发送
            case SerialPortEvent.DSR: // 数据设备准备好
            case SerialPortEvent.RI: // 响铃侦测
            case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空
                break;
            case SerialPortEvent.DATA_AVAILABLE: // 有数据到达
                // 调用读取数据的方法
                readComm();
                break;
            default:
                break;
        }
    }

    /**
     * 读取串口返回信息
     *
     * @author Jarvis
     * @return: void
     */
    public void readComm() {
        try {
            inputStream = serialPort.getInputStream();
            // 通过输入流对象的available方法获取数组字节长度
            byte[] readBuffer = new byte[inputStream.available()];
            // 从线路上读取数据流
            int len = 0;
            while ((len = inputStream.read(readBuffer)) != -1) {
                //获取串口返回数据
                data = new String(readBuffer, 0, len).trim();
                //转为十六进制数据
                dataHex = bytesToHexString(readBuffer);
                System.out.println("data:" + data);
                System.out.println("dataHex:" + dataHex);// 读取后置空流对象
                String recall = "FE010300000003FF";
                byte[] bytes1 = StringUtilss.hexToByteArray(recall.toString());
                SerialPortUtils.sendBite(bytes1);
                if(dataHex.length() > 18){
                    DetectionRlEjrl detectionRlEjrl = new DetectionRlEjrl();
                    String s = dataHex.substring(18);//010002004304F904F6FF
//                    System.out.println(s);
//                    System.out.println(s.substring(0,2));
//                    System.out.println(new BigInteger(s.substring(0,2).toUpperCase(), 16));//炉号 01
                    detectionRlEjrl.setLh(new BigInteger(s.substring(0,2).toUpperCase(), 16) + "");
//                    System.out.println(s.substring(2,6));
//                    System.out.println(new BigInteger(s.substring(2,6).toUpperCase(), 16));//炉次号 2
                    detectionRlEjrl.setLch(new BigInteger(s.substring(2,6).toUpperCase(), 16)+"");

//                    System.out.println(s.substring(6,10));
//                    System.out.println(hexToASCII(s.substring(6,10)));//C 元素
                    detectionRlEjrl.setElementType(hexToASCII(s.substring(6,10)));

//                    System.out.println(s.substring(10,14));
//                    System.out.println(new BigInteger(s.substring(10,14).toUpperCase(), 16));//1273理论加入值
                    detectionRlEjrl.setLlz(new BigInteger(s.substring(10,14).toUpperCase(), 16)+"");

//                    System.out.println(s.substring(14,18));
//                    System.out.println(new BigInteger(s.substring(14,18).toUpperCase(), 16));//1270 实际加入值
                    detectionRlEjrl.setSjz(new BigInteger(s.substring(14,18).toUpperCase(), 16)+"");
                    detectionRlEjrlMapper.insertDetectionRlEjrl(detectionRlEjrl);
                    System.out.println("写入辅料加入量一条" + detectionRlEjrl.toString());


                }
                inputStream.close();
                inputStream = null;
                break;
            }

        } catch (Exception e) {
            System.out.println(e);
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        String ss = "FE0103000000030006010002004304F904F6FF";
        String s = ss.substring(18);//010002004304F904F6FF
        System.out.println(s);
        System.out.println(s.substring(0,2));
        System.out.println(new BigInteger(s.substring(0,2).toUpperCase(), 16));//炉号 01

        System.out.println(s.substring(2,6));
        System.out.println(new BigInteger(s.substring(2,6).toUpperCase(), 16));//炉次号 2

        System.out.println(s.substring(6,10));
        System.out.println(hexToASCII(s.substring(6,10)));//C 元素
        System.out.println(s.substring(10,14));
        System.out.println(new BigInteger(s.substring(10,14).toUpperCase(), 16));//1273理论加入值
        System.out.println(s.substring(14,18));
        System.out.println(new BigInteger(s.substring(14,18).toUpperCase(), 16));//1270 实际加入值



    }
    public static String hexToASCII(String hex) {
        StringBuilder output = new StringBuilder();
        for (int i = 0; i < hex.length(); i += 2) {
            String str = hex.substring(i, i + 2);
            output.append((char) Integer.parseInt(str, 16));
        }
        return output.toString();
    }

    /**
     * 发送信息到串口
     *
     * @throws
     * @author Jarvis
     * @param: data
     * @return: void
     */
    public static void sendBite( byte[] orders) throws IOException {
        outputStream = serialPort.getOutputStream();
        for(byte b : orders){
            outputStream.write(b);
            outputStream.flush();
        }
        log.info("往串口 " + serialPort.getName() + " 发送数据:" + Arrays.toString(orders) + " 完成...");
    }
    public void sendComm(String data) {
        byte[] writerBuffer = null;
        try {
            writerBuffer = hexToByteArray(data);
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
        try {
            outputStream = serialPort.getOutputStream();
            outputStream.write(writerBuffer);
            outputStream.flush();
        } catch (NullPointerException e) {
            e.printStackTrace();
            ;
        } catch (IOException e) {
            e.printStackTrace();
            ;
        }
    }

    /**
     * 关闭串口
     *
     * @throws
     * @author Jarvis
     * @Description: 关闭串口
     * @param:
     * @return: void
     */
    public void closeSerialPort() {
        if (serialPort != null) {
            serialPort.notifyOnDataAvailable(false);
            serialPort.removeEventListener();
            if (inputStream != null) {
                try {
                    inputStream.close();
                    inputStream = null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                    outputStream = null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            serialPort.close();
            serialPort = null;
        }
    }

    /**
     * 十六进制串口返回值获取
     */
    public String getDataHex() {
        String result = dataHex;
        // 置空执行结果
        dataHex = null;
        // 返回执行结果
        return result;
    }

    /**
     * 串口返回值获取
     */
    public String getData() {
        String result = data;
        // 置空执行结果
        data = null;
        // 返回执行结果
        return result;
    }

    /**
     * Hex字符串转byte
     *
     * @param inHex 待转换的Hex字符串
     * @return 转换后的byte
     */
    public static byte hexToByte(String inHex) {
        return (byte) Integer.parseInt(inHex, 16);
    }

    /**
     * hex字符串转byte数组
     *
     * @param inHex 待转换的Hex字符串
     * @return 转换后的byte数组结果
     */
    public static byte[] hexToByteArray(String inHex) {
        int hexlen = inHex.length();
        byte[] result;
        if (hexlen % 2 == 1) {
            // 奇数
            hexlen++;
            result = new byte[(hexlen / 2)];
            inHex = "0" + inHex;
        } else {
            // 偶数
            result = new byte[(hexlen / 2)];
        }
        int j = 0;
        for (int i = 0; i < hexlen; i += 2) {
            result[j] = hexToByte(inHex.substring(i, i + 2));
            j++;
        }
        return result;
    }

    /**
     * 数组转换成十六进制字符串
     *
//     * @param byte[] bArray
     * @return HexString
     */
    public static final String bytesToHexString(byte[] bArray) {
        StringBuffer sb = new StringBuffer(bArray.length);
        String sTemp;
        for (int i = 0; i < bArray.length; i++) {
            sTemp = Integer.toHexString(0xFF & bArray[i]);
            if (sTemp.length() < 2)
                sb.append(0);
            sb.append(sTemp.toUpperCase());
        }
        return sb.toString();
    }


}

发送调用代码块:我把SerialPortUtils类的sendBite方法静态化了,可以直接在任何代码里直接调用。发送没有任何限制,但是你想在接收的时候,想在存有静态属性的方法里调用一下dao,service啥的,在依赖注入的时候(也就是@auwired),需要这么实现一下。如下图1,不然dao会报null的错误,注入失败。

String content = send;
                        int length = content.length();
                        int jcq = length / 4;// 不合格元素个数 * 4,再上位机收到光谱数转16进制
                        int zjs = jcq * 2;//寄存器数目*2再转16进制
                        sf.append(String2AcsII16.int10to16(jcq) +  String2AcsII16.int10to16(zjs));
                        sf.append(String2AcsII16.int10to16_2(1));
                        sf.append(String2AcsII16.int10to16(Integer.valueOf(lch)));
                        sf.append(content);
                        sf.append("FF");

                        byte[] bytes1 = StringUtilss.hexToByteArray(sf.toString());
//                        ChuanKou.sendStr16("COM5",bytes1);
                        SerialPortUtils.sendBite(bytes1);
//                        System.out.println("最终发送===向COM发送:" + sf.toString());

图一

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
好的,我可以为您提供一些 Java 实现 RS485 串口通信的基本步骤: 1. 导入相应的 Java 串口通信类库,例如 RXTX 或 jSerialComm。 2. 创建一个串口对象并设置串口参数,如波特率、数据位、停止位、校验等。 3. 实现串口事件监听器,当串口接收数据时,会触发相应的事件,从而执行数据接收操作。 4. 调用串口对象的 write() 方法发送数据,可以发送字符串或字节数组。 5. 解析接收到的数据,根据数据格式进行相应的处理。可以使用 Java 的字符串解析方法或者字节数组解析方法进行解析。 下面是一个简单的 Java RS485 串口通信示例代码: ```java import gnu.io.*; import java.io.*; public class SerialPortTest implements SerialPortEventListener { private SerialPort serialPort; private BufferedReader input; private OutputStream output; public static void main(String[] args) { try { SerialPort serialPort = (SerialPort) CommPortIdentifier.getPortIdentifier("COM1").open("SerialPortTest", 2000); serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); BufferedReader input = new BufferedReader(new InputStreamReader(serialPort.getInputStream())); OutputStream output = serialPort.getOutputStream(); serialPort.addEventListener(new SerialPortTest()); serialPort.notifyOnDataAvailable(true); } catch (Exception e) { e.printStackTrace(); } } public void serialEvent(SerialPortEvent event) { if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) { try { String inputLine = input.readLine(); System.out.println("Received data: " + inputLine); // 解析接收到的数据 // ... } catch (Exception e) { e.printStackTrace(); } } } public void sendData(String data) { try { output.write(data.getBytes()); } catch (Exception e) { e.printStackTrace(); } } } ``` 在上面的代码中,我们首先通过 CommPortIdentifier 类获取串口对象,并设置串口参数。然后创建 BufferedReader 和 OutputStream 对象用于读取和写入数据。接着实现 SerialPortEventListener 接口,当串口接收数据时,会触发 serialEvent() 方法进行数据接收和解析。最后,我们可以调用 sendData() 方法发送数据。 需要注意的是,在使用串口通信时,可能会遇到各种不同的问题,例如串口无法打开、数据接收错误等等。因此,在实际开发中,需要仔细测试和调试代码,确保串口通信能够正常进行。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

somdip

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值