欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

使用Java实现串口通信

程序员文章站 2024-03-11 14:12:19
本文实例为大家分享了java实现串口通信的具体代码,供大家参考,具体内容如下 1.介绍 使用java实现的串口通信程序,支持十六进制数据的发送与接收。 源码:ser...

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

1.介绍

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

效果图如下:

使用Java实现串口通信

2.rxtxcomm

java串口通信依赖的jar包rxtxcomm.jar
下载地址:

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

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