使用Java实现串口通信

作者:容华谢后 时间:2023-02-13 05:45:02 

本文实例为大家分享了Java实现串口通信的具体代码,供大家参考,具体内容如下

1.介绍

使用Java实现的串口通信程序,支持十六进制数据的发送与接收。
源码:SerialPortDemo

效果图如下:

使用Java实现串口通信

2.RXTXcomm

Java串口通信依赖的jar包RXTXcomm.jar
下载地址:http://download.csdn.net/detail/kong_gu_you_lan/9611334

内含32位与64位版本
使用方法:
拷贝 RXTXcomm.jar 到 JAVA_HOME\jre\lib\ext目录中;
拷贝 rxtxSerial.dll 到 JAVA_HOME\jre\bin目录中;
拷贝 rxtxParallel.dll 到 JAVA_HOME\jre\bin目录中;
JAVA_HOME为jdk安装路径

3.串口通信管理

SerialPortManager实现了对串口通信的管理,包括查找可用端口、打开关闭串口、发送接收数据。


package com.yang.serialport.manage;

import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.SerialPortEventListener;
import gnu.io.UnsupportedCommOperationException;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.TooManyListenersException;

import com.yang.serialport.exception.NoSuchPort;
import com.yang.serialport.exception.NotASerialPort;
import com.yang.serialport.exception.PortInUse;
import com.yang.serialport.exception.ReadDataFromSerialPortFailure;
import com.yang.serialport.exception.SendDataToSerialPortFailure;
import com.yang.serialport.exception.SerialPortInputStreamCloseFailure;
import com.yang.serialport.exception.SerialPortOutputStreamCloseFailure;
import com.yang.serialport.exception.SerialPortParameterFailure;
import com.yang.serialport.exception.TooManyListeners;

/**
* 串口管理
*
* @author yangle
*/
public class SerialPortManager {

/**
* 查找所有可用端口
*
* @return 可用端口名称列表
*/
@SuppressWarnings("unchecked")
public static final ArrayList<String> findPort() {
// 获得当前所有可用串口
Enumeration<CommPortIdentifier> portList = CommPortIdentifier
 .getPortIdentifiers();
ArrayList<String> portNameList = new ArrayList<String>();
// 将可用串口名添加到List并返回该List
while (portList.hasMoreElements()) {
 String portName = portList.nextElement().getName();
 portNameList.add(portName);
}
return portNameList;
}

/**
* 打开串口
*
* @param portName
*  端口名称
* @param baudrate
*  波特率
* @return 串口对象
* @throws SerialPortParameterFailure
*  设置串口参数失败
* @throws NotASerialPort
*  端口指向设备不是串口类型
* @throws NoSuchPort
*  没有该端口对应的串口设备
* @throws PortInUse
*  端口已被占用
*/
public static final SerialPort openPort(String portName, int baudrate)
 throws SerialPortParameterFailure, NotASerialPort, NoSuchPort,
 PortInUse {
try {
 // 通过端口名识别端口
 CommPortIdentifier portIdentifier = CommPortIdentifier
  .getPortIdentifier(portName);
 // 打开端口,设置端口名与timeout(打开操作的超时时间)
 CommPort commPort = portIdentifier.open(portName, 2000);
 // 判断是不是串口
 if (commPort instanceof SerialPort) {
 SerialPort serialPort = (SerialPort) commPort;
 try {
  // 设置串口的波特率等参数
  serialPort.setSerialPortParams(baudrate,
   SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
   SerialPort.PARITY_NONE);
 } catch (UnsupportedCommOperationException e) {
  throw new SerialPortParameterFailure();
 }
 return serialPort;
 } else {
 // 不是串口
 throw new NotASerialPort();
 }
} catch (NoSuchPortException e1) {
 throw new NoSuchPort();
} catch (PortInUseException e2) {
 throw new PortInUse();
}
}

/**
* 关闭串口
*
* @param serialport
*  待关闭的串口对象
*/
public static void closePort(SerialPort serialPort) {
if (serialPort != null) {
 serialPort.close();
 serialPort = null;
}
}

/**
* 向串口发送数据
*
* @param serialPort
*  串口对象
* @param order
*  待发送数据
* @throws SendDataToSerialPortFailure
*  向串口发送数据失败
* @throws SerialPortOutputStreamCloseFailure
*  关闭串口对象的输出流出错
*/
public static void sendToPort(SerialPort serialPort, byte[] order)
 throws SendDataToSerialPortFailure,
 SerialPortOutputStreamCloseFailure {
OutputStream out = null;
try {
 out = serialPort.getOutputStream();
 out.write(order);
 out.flush();
} catch (IOException e) {
 throw new SendDataToSerialPortFailure();
} finally {
 try {
 if (out != null) {
  out.close();
  out = null;
 }
 } catch (IOException e) {
 throw new SerialPortOutputStreamCloseFailure();
 }
}
}

/**
* 从串口读取数据
*
* @param serialPort
*  当前已建立连接的SerialPort对象
* @return 读取到的数据
* @throws ReadDataFromSerialPortFailure
*  从串口读取数据时出错
* @throws SerialPortInputStreamCloseFailure
*  关闭串口对象输入流出错
*/
public static byte[] readFromPort(SerialPort serialPort)
 throws ReadDataFromSerialPortFailure,
 SerialPortInputStreamCloseFailure {
InputStream in = null;
byte[] bytes = null;
try {
 in = serialPort.getInputStream();
 // 获取buffer里的数据长度
 int bufflenth = in.available();
 while (bufflenth != 0) {
 // 初始化byte数组为buffer中数据的长度
 bytes = new byte[bufflenth];
 in.read(bytes);
 bufflenth = in.available();
 }
} catch (IOException e) {
 throw new ReadDataFromSerialPortFailure();
} finally {
 try {
 if (in != null) {
  in.close();
  in = null;
 }
 } catch (IOException e) {
 throw new SerialPortInputStreamCloseFailure();
 }
}
return bytes;
}

/**
* 添加 *
*
* @param port
*  串口对象
* @param listener
*  串口 *
* @throws TooManyListeners
*  监听类对象过多
*/
public static void addListener(SerialPort port,
 SerialPortEventListener listener) throws TooManyListeners {
try {
 // 给串口添加 *
 port.addEventListener(listener);
 // 设置当有数据到达时唤醒监听接收线程
 port.notifyOnDataAvailable(true);
 // 设置当通信中断时唤醒中断线程
 port.notifyOnBreakInterrupt(true);
} catch (TooManyListenersException e) {
 throw new TooManyListeners();
}
}
}

4.程序主窗口


/*
* MainFrame.java
*
* Created on 2016.8.19
*/

package com.yang.serialport.ui;

import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;

import java.awt.Color;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import com.yang.serialport.exception.NoSuchPort;
import com.yang.serialport.exception.NotASerialPort;
import com.yang.serialport.exception.PortInUse;
import com.yang.serialport.exception.SendDataToSerialPortFailure;
import com.yang.serialport.exception.SerialPortOutputStreamCloseFailure;
import com.yang.serialport.exception.SerialPortParameterFailure;
import com.yang.serialport.exception.TooManyListeners;
import com.yang.serialport.manage.SerialPortManager;
import com.yang.serialport.utils.ByteUtils;
import com.yang.serialport.utils.ShowUtils;

/**
* 主界面
*
* @author yangle
*/
public class MainFrame extends JFrame {

/**
* 程序界面宽度
*/
public static final int WIDTH = 500;

/**
* 程序界面高度
*/
public static final int HEIGHT = 360;

private JTextArea dataView = new JTextArea();
private JScrollPane scrollDataView = new JScrollPane(dataView);

// 串口设置面板
private JPanel serialPortPanel = new JPanel();
private JLabel serialPortLabel = new JLabel("串口");
private JLabel baudrateLabel = new JLabel("波特率");
private JComboBox commChoice = new JComboBox();
private JComboBox baudrateChoice = new JComboBox();

// 操作面板
private JPanel operatePanel = new JPanel();
private JTextField dataInput = new JTextField();
private JButton serialPortOperate = new JButton("打开串口");
private JButton sendData = new JButton("发送数据");

private List<String> commList = null;
private SerialPort serialport;

public MainFrame() {
initView();
initComponents();
actionListener();
initData();
}

private void initView() {
// 关闭程序
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
// 禁止窗口最大化
setResizable(false);

// 设置程序窗口居中显示
Point p = GraphicsEnvironment.getLocalGraphicsEnvironment()
 .getCenterPoint();
setBounds(p.x - WIDTH / 2, p.y - HEIGHT / 2, WIDTH, HEIGHT);
this.setLayout(null);

setTitle("串口通讯");
}

private void initComponents() {
// 数据显示
dataView.setFocusable(false);
scrollDataView.setBounds(10, 10, 475, 200);
add(scrollDataView);

// 串口设置
serialPortPanel.setBorder(BorderFactory.createTitledBorder("串口设置"));
serialPortPanel.setBounds(10, 220, 170, 100);
serialPortPanel.setLayout(null);
add(serialPortPanel);

serialPortLabel.setForeground(Color.gray);
serialPortLabel.setBounds(10, 25, 40, 20);
serialPortPanel.add(serialPortLabel);

commChoice.setFocusable(false);
commChoice.setBounds(60, 25, 100, 20);
serialPortPanel.add(commChoice);

baudrateLabel.setForeground(Color.gray);
baudrateLabel.setBounds(10, 60, 40, 20);
serialPortPanel.add(baudrateLabel);

baudrateChoice.setFocusable(false);
baudrateChoice.setBounds(60, 60, 100, 20);
serialPortPanel.add(baudrateChoice);

// 操作
operatePanel.setBorder(BorderFactory.createTitledBorder("操作"));
operatePanel.setBounds(200, 220, 285, 100);
operatePanel.setLayout(null);
add(operatePanel);

dataInput.setBounds(25, 25, 235, 20);
operatePanel.add(dataInput);

serialPortOperate.setFocusable(false);
serialPortOperate.setBounds(45, 60, 90, 20);
operatePanel.add(serialPortOperate);

sendData.setFocusable(false);
sendData.setBounds(155, 60, 90, 20);
operatePanel.add(sendData);
}

@SuppressWarnings("unchecked")
private void initData() {
commList = SerialPortManager.findPort();
// 检查是否有可用串口,有则加入选项中
if (commList == null || commList.size() < 1) {
 ShowUtils.warningMessage("没有搜索到有效串口!");
} else {
 for (String s : commList) {
 commChoice.addItem(s);
 }
}

baudrateChoice.addItem("9600");
baudrateChoice.addItem("19200");
baudrateChoice.addItem("38400");
baudrateChoice.addItem("57600");
baudrateChoice.addItem("115200");
}

private void actionListener() {
serialPortOperate.addActionListener(new ActionListener() {

@Override
 public void actionPerformed(ActionEvent e) {
 if ("打开串口".equals(serialPortOperate.getText())
  && serialport == null) {
  openSerialPort(e);
 } else {
  closeSerialPort(e);
 }
 }
});

sendData.addActionListener(new ActionListener() {

@Override
 public void actionPerformed(ActionEvent e) {
 sendData(e);
 }
});
}

/**
* 打开串口
*
* @param evt
*  点击事件
*/
private void openSerialPort(java.awt.event.ActionEvent evt) {
// 获取串口名称
String commName = (String) commChoice.getSelectedItem();
// 获取波特率
int baudrate = 9600;
String bps = (String) baudrateChoice.getSelectedItem();
baudrate = Integer.parseInt(bps);

// 检查串口名称是否获取正确
if (commName == null || commName.equals("")) {
 ShowUtils.warningMessage("没有搜索到有效串口!");
} else {
 try {
 serialport = SerialPortManager.openPort(commName, baudrate);
 if (serialport != null) {
  dataView.setText("串口已打开" + "\r\n");
  serialPortOperate.setText("关闭串口");
 }
 } catch (SerialPortParameterFailure e) {
 e.printStackTrace();
 } catch (NotASerialPort e) {
 e.printStackTrace();
 } catch (NoSuchPort e) {
 e.printStackTrace();
 } catch (PortInUse e) {
 e.printStackTrace();
 ShowUtils.warningMessage("串口已被占用!");
 }
}

try {
 SerialPortManager.addListener(serialport, new SerialListener());
} catch (TooManyListeners e) {
 e.printStackTrace();
}
}

/**
* 关闭串口
*
* @param evt
*  点击事件
*/
private void closeSerialPort(java.awt.event.ActionEvent evt) {
SerialPortManager.closePort(serialport);
dataView.setText("串口已关闭" + "\r\n");
serialPortOperate.setText("打开串口");
}

/**
* 发送数据
*
* @param evt
*  点击事件
*/
private void sendData(java.awt.event.ActionEvent evt) {
// 输入框直接输入十六进制字符,长度必须是偶数
String data = dataInput.getText().toString();
try {
 SerialPortManager.sendToPort(serialport,
  ByteUtils.hexStr2Byte(data));
} catch (SendDataToSerialPortFailure e) {
 e.printStackTrace();
} catch (SerialPortOutputStreamCloseFailure e) {
 e.printStackTrace();
}
}

private class SerialListener implements SerialPortEventListener {
/**
 * 处理监控到的串口事件
 */
public void serialEvent(SerialPortEvent serialPortEvent) {

switch (serialPortEvent.getEventType()) {

case SerialPortEvent.BI: // 10 通讯中断
 ShowUtils.errorMessage("与串口设备通讯中断");
 break;

case SerialPortEvent.OE: // 7 溢位(溢出)错误

case SerialPortEvent.FE: // 9 帧错误

case SerialPortEvent.PE: // 8 奇偶校验错误

case SerialPortEvent.CD: // 6 载波检测

case SerialPortEvent.CTS: // 3 清除待发送数据

case SerialPortEvent.DSR: // 4 待发送数据准备好了

case SerialPortEvent.RI: // 5 振铃指示

case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 2 输出缓冲区已清空
 break;

case SerialPortEvent.DATA_AVAILABLE: // 1 串口存在可用数据
 byte[] data = null;
 try {
  if (serialport == null) {
  ShowUtils.errorMessage("串口对象为空!监听失败!");
  } else {
  // 读取串口数据
  data = SerialPortManager.readFromPort(serialport);
  dataView.append(ByteUtils.byteArrayToHexString(data,
   true) + "\r\n");
  }
 } catch (Exception e) {
  ShowUtils.errorMessage(e.toString());
  // 发生读取错误时显示错误信息后退出系统
  System.exit(0);
 }
 break;
 }
}
}

public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
 public void run() {
 new MainFrame().setVisible(true);
 }
});
}
}

5.写在最后

源码下载地址:SerialPortDemo

欢迎同学们吐槽评论,如果你觉得本篇博客对你有用,那么就留个言或者顶一下吧(^-^)

感谢:基于Java编写串口通信工具

来源:http://blog.csdn.net/kong_gu_you_lan/article/details/52302075

标签:java,串口通信
0
投稿

猜你喜欢

  • C++多重继承二义性原理实例解析

    2021-10-08 20:18:33
  • springboot动态调整日志级别的操作大全

    2023-11-03 19:31:12
  • java 实现定时的方法及实例代码

    2023-03-31 22:48:41
  • 关于Java中String类字符串的解析

    2021-06-24 20:15:06
  • C#学习教程之Socket的简单使用

    2022-09-07 18:15:04
  • unity实现虚拟摇杆控制Virtual Joystick

    2022-09-26 11:56:28
  • 举例讲解Java编程中this关键字与super关键字的用法

    2023-03-09 01:46:02
  • java 输入一个数字组成的数组(输出该数组的最大值和最小值)

    2023-11-24 21:41:58
  • Java实现贪吃蛇游戏

    2023-11-20 18:40:29
  • Java面向对象编程的三大特征

    2023-09-19 06:20:34
  • 【C#基础】Substring截取字符串的方法小结(推荐)

    2021-12-21 06:22:32
  • eclipse实现DSA数字签名

    2023-08-24 19:11:37
  • 深入剖析构建JSON字符串的三种方式(推荐)

    2023-09-26 07:47:22
  • Java中BigDecimal的加减乘除、比较大小与使用注意事项

    2022-02-17 21:24:09
  • Java线程生命周期图文详细讲解

    2022-07-17 05:22:32
  • 浅谈C#在网络波动时防重复提交的方法

    2022-07-23 22:37:01
  • SpringBoot整合MongoDB完整实例代码

    2023-10-22 03:42:48
  • Android实现滑动效果

    2022-09-20 15:04:24
  • 基于Java实现收发电子邮件功能

    2021-08-23 17:30:14
  • 浅谈Java线程并发知识点

    2021-10-20 13:11:13
  • asp之家 软件编程 m.aspxhome.com