jssc串口通信代码

这篇博客介绍了如何在Java开发中进行串口通信,提供了详细的maven依赖信息,并展示了具体的代码示例。

maven依赖:

<dependency>
    <groupId>io.github.java-native</groupId>
    <artifactId>jssc</artifactId>
    <version>2.9.4</version>
</dependency>

代码示例:
 

package com.hs.modbusstu.utils;

import jssc.SerialPort;
import jssc.SerialPortException;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * jssc工具类
 */
public class JsscUtilSingleton {

    public static final String HEX_PLACE_HOLDER = "0";
    /**
     * 十六进制进位阈值
     */
    public static final int HEX_CARRY_THRESHOLD = 15;


    private static class JsscUtil {
        public static final JsscUtilSingleton JSSC_UTIL_SINGLETON = new JsscUtilSingleton();
    }

    public static JsscUtilSingleton getInstance() {
        return JsscUtil.JSSC_UTIL_SINGLETON;
    }


    /**
     * 发送数据
     * 统一发送指令的方法
     *
     * @param serialPort
     * @param bytes      命令字节数组
     */
    public static List<String> sendData(SerialPort serialPort, byte[] bytes) {
        if (serialPort != null && serialPort.isOpened()) {
            try {
                serialPort.writeBytes(bytes);
                // 延时时间,50ms多次测试最稳当
                Thread.sleep(50);
                // 读取命令返回数据
                String[] resCode = serialPort.readHexStringArray();
                if (resCode == null || resCode.length == 0) {
                    return Collections.emptyList();
                } else {
                    System.out.println("命令发送后的返回值: " + Arrays.toString(resCode));
                    return Arrays.asList(resCode);
                }
            } catch (SerialPortException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        return Collections.emptyList();
    }

    public static String sendDataResStr(SerialPort serialPort, byte[] bytes) {
        if (serialPort != null && serialPort.isOpened()) {
            try {
                serialPort.writeBytes(bytes);
                // 延时时间,50ms多次测试最稳当
                Thread.sleep(50);
                // 读取命令返回数据
                String resCode = serialPort.readHexString();
                if (resCode == null || resCode.isEmpty()) {
                    return null;
                } else {
                    System.out.println("命令发送后的返回值: " + resCode);
                    return resCode.replaceAll(" ", "");
                }
            } catch (SerialPortException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        return null;
    }

    /**
     * jssc链接端口
     *
     * @param portName
     * @param baudRate
     * @return
     */
    public SerialPort openSerialPort(String portName, int baudRate) {
        final SerialPort serialPort = new SerialPort(portName);
        try {
            serialPort.openPort();
            serialPort.setParams(baudRate, 8, 1, 0);
            if (serialPort.isOpened()) {
                System.out.println("打开串口: " + serialPort.getPortName());
            }
        } catch (SerialPortException e) {
            throw new RuntimeException(e);
        }
        return serialPort;
    }

    /**
     * 关闭端口
     *
     * @param serialPort
     * @return
     */
    public static boolean closePort(final SerialPort serialPort) {
        try {
            return serialPort.closePort();
        } catch (SerialPortException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取校验和
     * 光谱仪
     *
     * @param lengthHigh
     * @param lengthLow
     * @param commandId
     * @param dataHigh
     * @param dataLow
     * @return
     */
    public static String getChecksum(int lengthHigh, int lengthLow, int commandId, int dataHigh, int dataLow) {
        // 求和
        int sumRes = lengthHigh + lengthLow + commandId + dataHigh + dataLow;
        int check = sumRes & 0xFF;

        System.out.println("check is: " + check);

        String checkStr = Integer.toHexString(check);
        if (check > HEX_CARRY_THRESHOLD) {
            return checkStr;
        } else {
            return HEX_PLACE_HOLDER + checkStr;
        }
    }

    /**
     * 初始化命令
     * 光谱仪
     *
     * @param commandId
     * @param data
     * @return
     */
    public static String generateCommand(int commandId, int data) {

        int dataLength = 0;
        if (data > 0) {
            // 当data有数据的时候则,数据位两位
            dataLength = 2;
        }

        // 从length到checksum
        int length = 4 + dataLength;

        int lengthHigh = (length >> 8) & 0xFF;

        // 低位
        int lengthlow = length & 0xFF;

        // 数据高位
        int dataHigh = (data >> 8) & 0xFF;
        int dataLow = data & 0xFF;

        // 计算checksum
        String checkSum = getChecksum(lengthHigh, lengthlow, commandId, dataHigh, dataLow);
        System.out.println("checkSum is: " + checkSum);

        // 构造命令
        StringBuilder commandStr = new StringBuilder("AA,55")
                // 设置长度length
                .append(lengthHigh <= 0 ? "00" : (lengthHigh > 15 ? Integer.toHexString(lengthHigh) : "0" + Integer.toHexString(lengthHigh)))
                .append(lengthlow <= 0 ? "00" : (lengthlow > 15 ? Integer.toHexString(lengthlow) : "0" + Integer.toHexString(lengthlow)))
                // commandId
                .append(commandId > 15 ? Integer.toHexString(commandId) : "0" + Integer.toHexString(commandId));

        // 如果0存在
        if (data > 0) {
            commandStr.append(dataHigh > 15 ? Integer.toHexString(dataHigh) : "0" + Integer.toHexString(dataHigh))
                    .append(dataLow > 15 ? Integer.toHexString(dataLow) : "0" + Integer.toHexString(dataLow));
        }

        //.append(dataHigh <= 0 ? "00" : (dataHigh > 15 ? Integer.toHexString(dataHigh) : "0" + Integer.toHexString(dataHigh)))
        //.append(dataLow <= 0 ? "00" : (dataLow > 15 ? Integer.toHexString(dataLow) : "0" + Integer.toHexString(dataLow)))
        // 设置checksum
        commandStr.append(checkSum);

        return commandStr.toString();
    }

    /**
     * 光谱仪发送命令封装
     *
     * @param commandId
     * @param data
     * @return
     */
    public static String spectrometerSendCommand(SerialPort serialPort, int commandId, int data) {

        // 构造命令字符串
        String commandStr = generateCommand(commandId, data);
        System.out.println("发送字符串命令: " + commandStr);
        // 十六进制字符串转字节数组
        byte[] command = hexStringToByteArray(commandStr);
        // 发送命令
        String resStr = sendDataResStr(serialPort, command);
        System.out.println("返回字符串为:" + resStr);
        // 光谱仪设置积分时间,如果第一次没发送成功则重新调用一次发送命令方法
        if (resStr == null) {
            resStr = JsscUtilSingleton.sendDataResStr(serialPort, command);
        }

        // 切出返回数据
        String dataStr = resStr.substring(10, resStr.length() - 2);
        System.out.println("切片出data值为: " + dataStr);
        return dataStr;

    }

    /**
     * 16进制转Ascii
     *
     * @param hexStr
     * @return
     */
    public static String hexToAscii(String hexStr) {
        StringBuilder output = new StringBuilder("");
        for (int i = 0; i < hexStr.length(); i += 2) {
            String str = hexStr.substring(i, i + 2);
            output.append((char) Integer.parseInt(str, 16));
        }
        return output.toString();
    }

    /**
     * 16进制表示的字符串转换为字节数组
     *
     * @param hexString 16进制表示的字符串
     * @return byte[] 字节数组
     */
    public static byte[] hexStringToByteArray(String hexString) {
        hexString = hexString.replaceAll(",", "");
        int len = hexString.length();
        byte[] bytes = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            // 两位一组,表示一个字节,把这样表示的16进制字符串,还原成一个字节
            bytes[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character
                    .digit(hexString.charAt(i + 1), 16));
        }
        return bytes;
    }


}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值