首页 > 编程 > Java > 正文

使用Java实现串口通信

2019-11-26 13:26:14
字体:
来源:转载
供稿:网友

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

1.介绍

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

效果图如下:

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编写串口通信工具

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表