java读写串口数据

文章介绍了如何在Java中进行串口通信,包括导入RXTXcomm库,处理UnsatisfiedLinkError错误,以及创建串口参数配置类和串口操作类进行数据读写。同时,提供了初始化串口、监听数据、发送数据和关闭串口的示例代码。
摘要由CSDN通过智能技术生成

最近接触到了串口及其读写,在此记录java进行串口读写的过程。

1.导入支持java串口通信的jar包:

在maven项目的pom.xml中添加RXTXcomm的依赖 或者 下载RXTXcomm.jar并导入到项目中。

支持Java串口通信操作的jar包,java.comm比较老,而且不支持64位系统,推荐使用Rxtx这个jar包(32位/64位均支持)。

下载地址:

https://files.cnblogs.com/files/Dreamer-1/mfz-rxtx-2.2-20081207-win-x86.zip (32位)

https://files.cnblogs.com/files/Dreamer-1/mfz-rxtx-2.2-20081207-win-x64.zip (64位)

注意:运行过程中抛出 java.lang.UnsatisfiedLinkError 错误或 gnu.io 下的类找不到时,将rxtx解压包中的 rxtxParallel.dll,rxtxSerial.dll 这两个文件复制到 C:\Windows\System32 目录下可解决该错误。

2.编写代码操作串口:

串口必要参数类:包含连接串口所必须的参数,方便在调用串口时设置和传递串口参数
复制代码

/**

  • 串口必要参数接收类

  • @author: LinWenLi

  • @date: 2018年7月21日 下午4:30:40
    */
    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;
      }

    getter()…
    setter()…
    }

复制代码

串口操作类:(其中包含的CustomException是自定义异常类,仅用于抛出异常原因。)
复制代码

import gnu.io.CommPortIdentifier;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import gnu.io.UnsupportedCommOperationException;

/**

  • 串口参数的配置 串口一般有如下参数可以在该串口打开以前进行配置: 包括串口号,波特率,输入/输出流控制,数据位数,停止位和奇偶校验。
    /
    // 注:串口操作类一定要继承SerialPortEventListener
    public class SerialPortUtils implements SerialPortEventListener {
    // 检测系统中可用的通讯端口类
    private CommPortIdentifier commPortId;
    // 枚举类型
    private Enumeration portList;
    // RS232串口
    private SerialPort serialPort;
    // 输入流
    private InputStream inputStream;
    // 输出流
    private OutputStream outputStream;
    // 保存串口返回信息
    private String data;
    // 保存串口返回信息十六进制
    private String dataHex;/
    *

    • 初始化串口
    • @author LinWenLi
    • @date 2018年7月21日下午3:44:16
    • @Description: TODO
    • @param: paramConfig 存放串口连接必要参数的对象(会在下方给出类代码)
    • @return: void
    • @throws
      */
      @SuppressWarnings(“unchecked”)
      public void init(ParamConfig paramConfig) {
      // 获取系统中所有的通讯端口
      portList = CommPortIdentifier.getPortIdentifiers();
      // 记录是否含有指定串口
      boolean isExsist = false;
      // 循环通讯端口
      while (portList.hasMoreElements()) {
      commPortId = portList.nextElement();
      // 判断是否是串口
      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.addEventListener(this);
      // 设置串口数据时间有效(可监听)
      serialPort.notifyOnDataAvailable(true);
      // 设置串口通讯参数:波特率,数据位,停止位,校验方式
      serialPort.setSerialPortParams(paramConfig.getBaudRate(), paramConfig.getDataBit(),
      paramConfig.getStopBit(), paramConfig.getCheckoutBit());
      } catch (PortInUseException e) {
      throw new CustomException(“端口被占用”);
      } catch (TooManyListenersException e) {
      throw new CustomException(“监听器过多”);
      } catch (UnsupportedCommOperationException e) {
      throw new CustomException(“不支持的COMM端口操作异常”);
      }
      // 结束循环
      break;
      }
      }
      }
      // 若不存在该串口则抛出异常
      if (!isExsist) {
      throw new CustomException(“不存在该串口!”);
      }
      }

    /**

    • 实现接口SerialPortEventListener中的方法 读取从串口中接收的数据
      */
      @Override
      public void serialEvent(SerialPortEvent event) {
      switch (event.getEventType()) {
      case SerialPortEvent.BI: // 通讯中断
      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 LinWenLi
    • @date 2018年7月21日下午3:43:04
    • @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);// 读取后置空流对象
      inputStream.close();
      inputStream = null;
      break;
      }
      } catch (IOException e) {
      throw new CustomException(“读取串口数据时发生IO异常”);
      }
      }

    /**

    • 发送信息到串口
    • @author LinWenLi
    • @date 2018年7月21日下午3:45:22
    • @param: data
    • @return: void
    • @throws
      */
      public void sendComm(String data) {
      byte[] writerBuffer = null;
      try {
      writerBuffer = hexToByteArray(data);
      } catch (NumberFormatException e) {
      throw new CustomException(“命令格式错误!”);
      }
      try {
      outputStream = serialPort.getOutputStream();
      outputStream.write(writerBuffer);
      outputStream.flush();
      } catch (NullPointerException e) {
      throw new CustomException(“找不到串口。”);
      } catch (IOException e) {
      throw new CustomException(“发送信息到串口时发生IO异常”);
      }
      }

    /**

    • 关闭串口
    • @author LinWenLi
    • @date 2018年7月21日下午3:45:43
    • @Description: 关闭串口
    • @param:
    • @return: void
    • @throws
      */
      public void closeSerialPort() {
      if (serialPort != null) {
      serialPort.notifyOnDataAvailable(false);
      serialPort.removeEventListener();
      if (inputStream != null) {
      try {
      inputStream.close();
      inputStream = null;
      } catch (IOException e) {
      throw new CustomException(“关闭输入流时发生IO异常”);
      }
      }
      if (outputStream != null) {
      try {
      outputStream.close();
      outputStream = null;
      } catch (IOException e) {
      throw new CustomException(“关闭输出流时发生IO异常”);
      }
      }
      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[]
    • @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();
      }
      }

复制代码

调用串口操作类的代码:
复制代码

 public static void main(String[] args) {
     // 实例化串口操作类对象
     SerialPortUtils serialPort = new SerialPortUtils();
     // 创建串口必要参数接收类并赋值,赋值串口号,波特率,校验位,数据位,停止位
     ParamConfig paramConfig = new ParamConfig("COM4", 9600, 0, 8, 1);
     // 初始化设置,打开串口,开始监听读取串口数据
     serialPort.init(paramConfig);
     // 调用串口操作类的sendComm方法发送数据到串口
     serialPort.sendComm("FEF10A000000000000000AFF");
     // 关闭串口(注意:如果需要接收串口返回数据的,请不要执行这句,保持串口监听状态)
     serialPort.closeSerialPort();
 }

复制代码

当执行main方法中的代码且未执行关闭串口时,程序将一直处于开启状态,自动监听,接收读取来自串口的数据。

注意:一个串口只能打开一次,并只支持一个程序调用。

以上所记录的是简单测试java是否能成功操作串口数据,至于本人所写的Web端的读卡器调试功能则是在串口操作类的基础上编写网页界面,通过请求来控制串口的开启关闭及相应的设置,功能比较简单,放个界面记录一下:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要在Java读取串口字符串数据,需要使用Java串口通信API。以下是一个简单的示例代码,演示如何使用Java串口通信API读取串口字符串数据: ``` import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.OutputStream; import java.util.Enumeration; import gnu.io.CommPortIdentifier; import gnu.io.SerialPort; public class SerialTest { public static void main(String[] args) { // 获取所有可用串口 Enumeration portList = CommPortIdentifier.getPortIdentifiers(); while (portList.hasMoreElements()) { CommPortIdentifier portId = (CommPortIdentifier) portList.nextElement(); if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { System.out.println("发现可用串口:" + portId.getName()); } } // 打开串口 try { String portName = "/dev/ttyUSB0"; // 更改为你的串口名称 CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName); SerialPort serialPort = (SerialPort) portIdentifier.open("SerialTest", 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(); // 读取串口数据 while (true) { String inputLine = input.readLine(); System.out.println("收到数据:" + inputLine); } } catch (Exception e) { System.err.println(e.toString()); } } } ``` 在以上代码中,我们使用了Java串口通信API中的`CommPortIdentifier`、`SerialPort`、`BufferedReader`和`OutputStream`等类。我们首先获取所有可用的串口,然后打开指定的串口,并设置串口参数。接着,我们获取输入输出流,使用`BufferedReader`读取串口数据。在读取数据时,我们将其打印出来。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

K_s-huang

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

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

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

打赏作者

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

抵扣说明:

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

余额充值