java实现 串口通讯

 参考 Java实现串口通信_我不吃芹菜的博客-CSDN博客_java 串口

 java 串口通讯,直接控制报警灯的灯亮和播放音乐。

报警灯接口文档:接收16进制数组 。

报警灯指令文档:

 工具方法: hexToByte ()   把16进制 转成 bit,传参会用到。

    public static byte hexToByte(String arg) {
        int val = Integer.valueOf(arg, 16).intValue();
        byte c = (byte) (val & 0xff);
        return c;
    }

实现类 Chuankou.java

package com.hs.server;

import com.hs.util.NumberUtils;
import gnu.io.*;
import lombok.extern.slf4j.Slf4j;

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

/**
 * 串口通讯  modbus 485
 */
@Slf4j
public class ChuanKou {
   public static SerialPort port = null;
    /**
     * 打开电脑上指定的串口
     *
     * @param portName 端口名称,如 COM1,为 null 时,默认使用电脑中能用的端口中的第一个
     * @param b        波特率(baudrate),如 9600
     * @param d        数据位(datebits),如 SerialPort.DATABITS_8 = 8
     * @param s        停止位(stopbits),如 SerialPort.STOPBITS_1 = 1
     * @param p        校验位 (parity),如 SerialPort.PARITY_NONE = 0
     * @return 打开的串口对象,打开失败时,返回 null
     */
    public static final SerialPort openComPort(String portName, int b, int d, int s, int p) {
        Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();
        CommPort commPort = null;
        try {
            //当没有传入可用的 com 口时,默认使用电脑中可用的 com 口中的第一个
//            if (portName == null || "".equals(portName)) {
//                List<String> comPortList = findSystemAllComPort();
//                if (comPortList != null && comPortList.size() > 0) {
//                    portName = comPortList.get(0);
//                }
//            }
            log.info("开始打开串口:portName=" + portName + ",baudrate=" + b + ",datebits=" + d + ",stopbits=" + s + ",parity=" + p);

            //通过端口名称识别指定 COM 端口
            CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
            /**
             * open(String TheOwner, int i):打开端口
             * TheOwner 自定义一个端口名称,随便自定义即可
             * i:打开的端口的超时时间,单位毫秒,超时则抛出异常:PortInUseException if in use.
             * 如果此时串口已经被占用,则抛出异常:gnu.io.PortInUseException: Unknown Application
             */
            commPort = portIdentifier.open(portName, 5000);
            /**
             * 判断端口是不是串口
             * public abstract class SerialPort extends CommPort
             */
            if (commPort instanceof SerialPort) {
                SerialPort serialPort = (SerialPort) commPort;
                port = serialPort;
                /**
                 * 设置串口参数:setSerialPortParams( int b, int d, int s, int p )
                 * b:波特率(baudrate)
                 * d:数据位(datebits),SerialPort 支持 5,6,7,8
                 * s:停止位(stopbits),SerialPort 支持 1,2,3
                 * p:校验位 (parity),SerialPort 支持 0,1,2,3,4
                 * 如果参数设置错误,则抛出异常:gnu.io.UnsupportedCommOperationException: Invalid Parameter
                 * 此时必须关闭串口,否则下次 portIdentifier.open 时会打不开串口,因为已经被占用
                 */
                serialPort.setSerialPortParams(b, d, s, p);
                log.info("打开串口 " + portName + " 成功...");
                return serialPort;
            } else {
                log.error("当前端口 " + commPort.getName() + " 不是串口...");
            }
        } catch (NoSuchPortException e) {
            log.info("NoSuchPortException === ");
            e.printStackTrace();
        } catch (PortInUseException e) {
            log.warn("串口 " + portName + " 已经被占用,请先解除占用...");
            e.printStackTrace();
        } catch (UnsupportedCommOperationException e) {
            log.warn("串口参数设置错误,关闭串口,数据位[5-8]、停止位[1-3]、验证位[0-4]...");
            e.printStackTrace();
            if (commPort != null) {//此时必须关闭串口,否则下次 portIdentifier.open 时会打不开串口,因为已经被占用
                commPort.close();
            }
        }
        log.error("打开串口 " + portName + " 失败...");
        return null;
    }

    /**
     * 往串口发送数据
     *
     * @param serialPort 串口对象
     */
    public static void sendDataToComPort(SerialPort serialPort, byte[] orders) {
        OutputStream outputStream = null;
        try {
            if (serialPort != null) {
                outputStream = serialPort.getOutputStream();
                outputStream.write(orders);
                outputStream.flush();
                log.info("往串口 " + serialPort.getName() + " 发送数据:" + Arrays.toString(orders) + " 完成...");
            } else {
                log.error("gnu.io.SerialPort 为null,取消数据发送...");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /**
     * 关闭串口
     *
     * @param serialPort 待关闭的串口对象
     */
    public static void closeComPort(SerialPort serialPort) {
        if (serialPort != null) {
            serialPort.close();
            log.info("关闭串口 " + serialPort.getName());
        }else{
            log.info("串口未关闭,串口为空");
        }
    }

    public static void main(String[] args) {
        String string = Integer.toHexString(31);
        System.out.println(string);
//        SerialPort serialPort = ChuanKou.openComPort("COM7", 9600, 8, 1, 502);
//        byte[] orders = {01,06,31,03,00,04};
//        ChuanKou.sendDataToComPort(serialPort,orders);
        System.out.println(Integer.parseInt(string,16));;
    }

    public static void WARN(String com){
        if(com==null){
            com="COM7";
        }
        SerialPort serialPort = ChuanKou.openComPort(com, 9600, 8, 1, 0);
        byte[] orders = {NumberUtils.hexToByte("FF"),
                NumberUtils.hexToByte("06"),
                NumberUtils.hexToByte("11"),
                NumberUtils.hexToByte("03"),
                NumberUtils.hexToByte("00"),
                NumberUtils.hexToByte("04"),
                NumberUtils.hexToByte("68"),
                NumberUtils.hexToByte("EB")};
        ChuanKou.sendDataToComPort(serialPort,orders);
        ChuanKou.closeComPort(ChuanKou.port);

    }


}

遇到的问题及解决

一、java崩溃,原因缺少RXTXcomm.jar 包 和rxtxSerial.dll 配置

no rxtxSerial64 in java.library.path thrown while loading gnu.io.RXTXCommDriver

 

解决: 

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

如图:

文件传送门

链接:https://pan.baidu.com/s/1b_3aufETiBnv2bv5zDeLLw 
提取码:41f4 

二、 jdk版本不合适

# A fatal error has been detected by the Java Runtime Environment:

java version "1.8.0_341"
Java(TM) SE Runtime Environm

See problematic frame for where to report the bug.

解决:jdk使用1.8.031版本。 

相关附件传送门:

链接:https://pan.baidu.com/s/1VYjca_iTOklvcJrxHYWxkA 
提取码:y961

补充:获取校验码,传入参数的前几位,获取后两位的校验码,每次换前面的参数都要重新获取校验码。比如选择绿灯红灯还是爆闪常亮。

/**
     * 获取校验码
     * crc16 X16+x15+x2+1
     * 16进制报文是 02 03 00 00 00 40 CRC16
     * 传输的str:“020300000040”
     * 结果:4409
     * @param str
     * @return
     */
    public static String getCRC(String str) {
        byte[] bytes = NumberUtils.hexStringToBytes(str);
        int CRC = 0x0000ffff;
        int POLYNOMIAL = 0x0000a001;

        int i, j;
        for (i = 0; i < bytes.length; i++) {
            CRC ^= ((int) bytes[i] & 0x000000ff);
            for (j = 0; j < 8; j++) {
                if ((CRC & 0x00000001) != 0) {
                    CRC >>= 1;
                    CRC ^= POLYNOMIAL;
                } else {
                    CRC >>= 1;
                }
            }
        }
        String crc = Integer.toHexString(CRC);
        if (crc.length() == 2) {
            crc = "00" + crc;
        } else if (crc.length() == 3) {
            crc = "0" + crc;
        }
        crc = crc.substring(2, 4) + crc.substring(0, 2);
        return crc.toUpperCase();
    }

拓展:

控制报警灯亮的时间的方法有两种:

一是选择想要播放时间长的音乐文件

二是用程序控制,亮灯指令和关灯指令,中间休息想要的时间。 

   public static void WARN(String com){
        if(com==null){
            com="COM7";
        }
        SerialPort serialPort = ChuanKou.openComPort(com, 9600, 8, 1, 0);
        byte[] orders = {NumberUtils.hexToByte("FF"),
                NumberUtils.hexToByte("06"),
                NumberUtils.hexToByte("31"),
                NumberUtils.hexToByte("03"),
                NumberUtils.hexToByte("00"),
                NumberUtils.hexToByte("04"),
                NumberUtils.hexToByte("63"),
                NumberUtils.hexToByte("2B")};
        ChuanKou.sendDataToComPort(serialPort,orders);//制定串口发送指令
        ChuanKou.closeComPort(ChuanKou.port);//关闭报警灯

    }

  • 10
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
### 回答1: 我非常乐意为您提供有关Java串口通信类的源代码。下面是一个简单的Java串口通信类示例,其中包含了一些常见的串口通信操作。 ```java import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Enumeration; import gnu.io.CommPort; import gnu.io.CommPortIdentifier; import gnu.io.SerialPort; public class SerialCommunication { private SerialPort serialPort; private InputStream in; private OutputStream out; public void connect(String portName) throws Exception { CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName); if (portIdentifier.isCurrentlyOwned()) { System.out.println("无法连接到指定串口,该端口已经被占用."); } else { CommPort commPort = portIdentifier.open(this.getClass().getName(), 2000); if (commPort instanceof SerialPort) { serialPort = (SerialPort) commPort; serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); in = serialPort.getInputStream(); out = serialPort.getOutputStream(); System.out.println("成功连接到串口."); } else { System.out.println("指定端口类型错误."); } } } public void disconnect() { try { if (in != null) in.close(); if (out != null) out.close(); if (serialPort != null) serialPort.close(); System.out.println("已断开与串口的连接."); } catch (IOException e) { e.printStackTrace(); } } public void sendData(String data) throws IOException { out.write(data.getBytes()); out.flush(); System.out.println("已发送数据: " + data); } public String receiveData() throws IOException { byte[] buffer = new byte[1024]; int len = in.read(buffer); return new String(buffer, 0, len); } public static void main(String[] args) { try { SerialCommunication communication = new SerialCommunication(); communication.connect("COM1"); // 连接到COM1串口 communication.sendData("Hello, Serial Port!"); // 发送数据到串口 String receivedData = communication.receiveData(); // 接收来自串口的数据 System.out.println("接收到的数据: " + receivedData); communication.disconnect(); // 断开与串口的连接 } catch (Exception e) { e.printStackTrace(); } } } ``` 以上代码是一个简单的Java串口通信类示例,其中包括了连接、断开连接、发送数据和接收数据等基本操作。在使用时,您需要添加对 `gnu.io` 包的依赖,并根据实际情况修改串口名称、波特率等参数。此外,还要确保您的计算机已经安装了正确的串口驱动程序。 请注意,此代码仅作为示例和参考之用。在实际开发中,建议使用现有的Java串口通信库,例如rxtx或jSerialComm,以简化开发过程并提供更多功能和稳定性。 ### 回答2: 串口通信是指通过串口进行数据传输的一种通信方式。在Java中,可以通过使用串口通信类,来实现串口通信。下面是一个简化的串口通信类的源码示例: ```java import gnu.io.*; public class SerialPortCommunication { private SerialPort serialPort; // 串口对象 public SerialPortCommunication(String portName, int baudRate) { try { CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName); // 获取串口标识符 serialPort = (SerialPort) portIdentifier.open(this.getClass().getName(), 2000); // 打开串口 serialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); // 设置串口参数 } catch (Exception e) { e.printStackTrace(); } } public void sendData(String data) { try { OutputStream outputStream = serialPort.getOutputStream(); // 获取串口输出流 byte[] bytes = data.getBytes(); outputStream.write(bytes); // 发送数据 } catch (Exception e) { e.printStackTrace(); } } public String receiveData() { String result = ""; try { InputStream inputStream = serialPort.getInputStream(); // 获取串口输入流 byte[] buffer = new byte[1024]; int len = inputStream.read(buffer); // 读取串口数据 result = new String(buffer, 0, len); } catch (Exception e) { e.printStackTrace(); } return result; } public void close() { serialPort.close(); // 关闭串口 } } ``` 以上是一个简单的串口通信类的源码示例。通过该类,你可以创建一个串口通信对象,并通过调用 `sendData()` 方法发送数据,通过调用 `receiveData()` 方法接收串口数据,通过 `close()` 方法关闭串口连接。在实际使用时,还需要根据具体项目需求进行更完善的错误处理和数据解析等功能。 ### 回答3: Java 串口通信类的源码实现主要是通过Java内置的Comm API或者使用第三方库来实现串口通信功能。 以下是一个简单的例子,展示了如何使用Comm API来进行串口通信: ```java import java.io.*; import java.util.*; import javax.comm.*; public class SerialCommunication { private static Enumeration portList; private static CommPortIdentifier portId; private static SerialPort serialPort; private static OutputStream outputStream; public static void main(String[] args) { try { // 获取可用的串口列表 portList = CommPortIdentifier.getPortIdentifiers(); // 遍历串口列表并找到需要使用的串口 while (portList.hasMoreElements()) { portId = (CommPortIdentifier) portList.nextElement(); if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { if (portId.getName().equals("COM1")) { // 假设需要使用COM1串口 // 打开串口并设置参数 serialPort = (SerialPort) portId.open("SerialCommunication", 2000); serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); // 获取输出流,用于发送数据 outputStream = serialPort.getOutputStream(); // 发送数据到串口 outputStream.write("Hello, Serial!".getBytes()); serialPort.close(); // 关闭串口 } } } } catch (Exception e) { e.printStackTrace(); } } } ``` 上述代码使用了CommPortIdentifier类来列举可用的串口,并通过SerialPort类来打开指定的串口。然后,通过设置SerialPort的参数,例如波特率、数据位数、停止位和校验位等,在实际应用中应根据具体需求进行配置。接着,获取输出流并将数据发送到打开的串口。最后,关闭串口。 需要注意的是,以上代码仅为示例,实际使用时请根据具体的硬件设备和通信协议进行相应的修改和调整。 此外,还可以使用其他第三方库实现串口通信,例如RXTXcomm或者jSerialComm等。这些库提供了更多的功能和灵活性,让串口通信更加方便和易用。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

somdip

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

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

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

打赏作者

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

抵扣说明:

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

余额充值