评论

收藏

[Java] java使用Rxtx实现串口通信调试工具

编程语言 编程语言 发布于:2021-10-06 12:02 | 阅读数:326 | 评论:0

这篇文章主要为大家详细介绍了java使用Rxtx实现简单串口通信调试工具,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
本文实例为大家分享了java使用rxtx实现串口通信调试工具的具体代码,供大家参考,具体内容如下
最终效果如下图:
DSC0000.jpg

1、把rxtxparallel.dll、rxtxserial.dll拷贝到:c:\windows\system32下。
2、rxtxcomm.jar 添加到项目类库中。
代码:
package serialport;
 
import java.io.ioexception;
import java.io.inputstream;
import java.io.outputstream;
import java.util.arraylist;
import java.util.enumeration;
import java.util.list;
import java.util.toomanylistenersexception;
 
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;
 
/**串口服务类,提供打开、关闭串口,读取、发送串口数据等服务
 */
public class serialtool {
 
 private static serialtool serialtool = null;
 
 static {
  //在该类被classloader加载时就初始化一个serialtool对象
  if (serialtool == null) {
   serialtool = new serialtool();
  }
 }
 
 //私有化serialtool类的构造方法,不允许其他类生成serialtool对象
 private serialtool() {} 
 /**
  * 获取提供服务的serialtool对象
  * @return serialtool
  */
 public static serialtool getserialtool() {
 
  if (serialtool == null) {
   serialtool = new serialtool();
  }
  return serialtool;
 }
 /**
  * 查找所有可用端口
  * @return 可用端口名称列表
  */
 public static final list<string> findport() {
 
  //获得当前所有可用串口
  @suppresswarnings("unchecked")
  enumeration<commportidentifier> portlist = commportidentifier.getportidentifiers(); 
  list<string> portnamelist = new arraylist<>();
  //将可用串口名添加到list并返回该list
  while (portlist.hasmoreelements()) {
   string portname = portlist.nextelement().getname();
   portnamelist.add(portname);
  }
  return portnamelist;
 }
 /**
  * 打开串口
  * @param portname 端口名称
  * @param baudrate 波特率
  * @return 串口对象
  * @throws unsupportedcommoperationexception
  * @throws portinuseexception
  * @throws nosuchportexception
  */
 public static final serialport openport(string portname, int baudrate) throws unsupportedcommoperationexception, portinuseexception, nosuchportexception {
 
  //通过端口名识别端口
  commportidentifier portidentifier = commportidentifier.getportidentifier(portname);
  //打开端口,并给端口名字和一个timeout(打开操作的超时时间)
  commport commport = portidentifier.open(portname, 2000);
  //判断是不是串口
  if (commport instanceof serialport) {
   serialport serialport = (serialport) commport;
   //设置一下串口的波特率等参数
   serialport.setserialportparams(baudrate, serialport.databits_8, serialport.stopbits_1, serialport.parity_none);    
   return serialport;
  }
  return null;
 }
 /**
  * 关闭串口
  * @param serialport 待关闭的串口对象
  */
 public static void closeport(serialport serialport) {
 
  if (serialport != null) {
   serialport.close();
   serialport = null;
  }
 }
 /**
  * 往串口发送数据
  * @param serialport 串口对象
  * @param order 待发送数据
  * @throws ioexception 
  */
 public static void sendtoport(serialport serialport, byte[] order) throws ioexception {
 
  outputstream out = null;
  out = serialport.getoutputstream();
  out.write(order);
  out.flush();
  out.close();
 }
 /**
  * 从串口读取数据
  * @param serialport 当前已建立连接的serialport对象
  * @return 读取到的数据
  * @throws ioexception 
  */
 public static byte[] readfromport(serialport serialport) throws ioexception {
 
  inputstream in = null;
  byte[] bytes = null;
  try {
   in = serialport.getinputstream();
   int bufflenth = in.available(); //获取buffer里的数据长度
   while (bufflenth != 0) {    
  bytes = new byte[bufflenth]; //初始化byte数组为buffer中数据的长度
  in.read(bytes);
  bufflenth = in.available();
   } 
  } catch (ioexception e) {
   throw e;
  } finally {
   if (in != null) {
  in.close();
  in = null;
   }
  }
  return bytes;
 }
 /**添加监听器
  * @param port  串口对象
  * @param listener 串口监听器
  * @throws toomanylistenersexception 
  */
 public static void addlistener(serialport port, serialporteventlistener listener) throws toomanylistenersexception {
 
  //给串口添加监听器
  port.addeventlistener(listener);
  //设置当有数据到达时唤醒监听接收线程
  port.notifyondataavailable(true);
  //设置当通信中断时唤醒中断线程
  port.notifyonbreakinterrupt(true);
 }
}
package serialport;
 
import java.awt.color;
import java.awt.font;
import java.awt.image;
import java.awt.toolkit;
import java.awt.event.actionevent;
import java.awt.event.actionlistener;
import java.awt.event.mouseadapter;
import java.awt.event.mouseevent;
import java.io.ioexception;
import java.time.instant;
import java.time.localdatetime;
import java.time.zoneid;
import java.time.format.datetimeformatter;
import java.util.list;
import java.util.timer;
import java.util.timertask;
import java.util.toomanylistenersexception;
 
import javax.swing.jbutton;
import javax.swing.jcombobox;
import javax.swing.jframe;
import javax.swing.jlabel;
import javax.swing.joptionpane;
import javax.swing.jscrollpane;
import javax.swing.jtextarea;
import javax.swing.border.titledborder;
 
import gnu.io.nosuchportexception;
import gnu.io.portinuseexception;
import gnu.io.serialport;
import gnu.io.serialportevent;
import gnu.io.serialporteventlistener;
import gnu.io.unsupportedcommoperationexception;
 
/**
 * 监测数据显示类
 * @author zhong
 *
 */
public class serialview extends jframe {
 
 /**
  */
 private static final long serialversionuid = 1l;
 
 //设置window的icon
 toolkit toolkit = gettoolkit();
 image icon = toolkit.getimage(serialview.class.getresource("computer.png"));
 datetimeformatter df= datetimeformatter.ofpattern("yyyy-mm-dd hh:mm:ss.sss");
 
 private jcombobox<string> commchoice;
 private jcombobox<string> bpschoice;
 private jbutton openserialbutton;
 private jbutton sendbutton;
 private jtextarea sendarea;
 private jtextarea receivearea;
 private jbutton closeserialbutton;
 
 private list<string> commlist = null; //保存可用端口号
 private serialport serialport = null; //保存串口对象
 
 /**类的构造方法
  * @param client
  */
 public serialview() {
 
  init();
  timertask task = new timertask() { 
   @override
   public void run() { 
  commlist = serialtool.findport(); //程序初始化时就扫描一次有效串口
  //检查是否有可用串口,有则加入选项中
  if (commlist == null || commlist.size()<1) {
   joptionpane.showmessagedialog(null, "没有搜索到有效串口!", "错误", joptionpane.information_message);
  }else{
   commchoice.removeallitems();
   for (string s : commlist) {
    commchoice.additem(s);
   }
  }
   }
  };
  timer timer = new timer(); 
  timer.scheduleatfixedrate(task, 0, 10000);
  listen();
 
 }
 /**
  */
 private void listen(){
 
  //打开串口连接
  openserialbutton.addactionlistener(new actionlistener() {
 
   public void actionperformed(actionevent e) {
  //获取串口名称
  string commname = (string) commchoice.getselecteditem();   
  //获取波特率
  string bpsstr = (string) bpschoice.getselecteditem();
  //检查串口名称是否获取正确
  if (commname == null || commname.equals("")) {
   joptionpane.showmessagedialog(null, "没有搜索到有效串口!", "错误", joptionpane.information_message);   
  }else {
   //检查波特率是否获取正确
   if (bpsstr == null || bpsstr.equals("")) {
    joptionpane.showmessagedialog(null, "波特率获取错误!", "错误", joptionpane.information_message);
   }else {
    //串口名、波特率均获取正确时
    int bps = integer.parseint(bpsstr);
    try {
     //获取指定端口名及波特率的串口对象
     serialport = serialtool.openport(commname, bps);
     serialtool.addlistener(serialport, new seriallistener());
     if(serialport==null) return;
     //在该串口对象上添加监听器
     closeserialbutton.setenabled(true);
     sendbutton.setenabled(true);
     openserialbutton.setenabled(false);
     string time=df.format(localdatetime.ofinstant(instant.ofepochmilli(system.currenttimemillis()),zoneid.of("asia/shanghai")));
     receivearea.append(time+" ["+serialport.getname().split("/")[3]+"] : "+" 连接成功..."+"\r\n");
     receivearea.setcaretposition(receivearea.gettext().length()); 
    } catch (unsupportedcommoperationexception | portinuseexception | nosuchportexception | toomanylistenersexception e1) {
     e1.printstacktrace();
    }
   }
  }
   }
  });
  //发送数据
  sendbutton.addmouselistener(new mouseadapter() {
   @override
   public void mouseclicked(mouseevent e) {
  if(!sendbutton.isenabled())return;
  string message= sendarea.gettext();
  //"fe0400030001d5c5"
  try {
   serialtool.sendtoport(serialport, hex2byte(message));
  } catch (ioexception e1) {
   e1.printstacktrace();
  }
   }
  });
  //关闭串口连接
  closeserialbutton.addmouselistener(new mouseadapter() {
   @override
   public void mouseclicked(mouseevent e) {
  if(!closeserialbutton.isenabled())return;
  serialtool.closeport(serialport);
  string time=df.format(localdatetime.ofinstant(instant.ofepochmilli(system.currenttimemillis()),zoneid.of("asia/shanghai")));
  receivearea.append(time+" ["+serialport.getname().split("/")[3]+"] : "+" 断开连接"+"\r\n");
  receivearea.setcaretposition(receivearea.gettext().length()); 
  openserialbutton.setenabled(true);
  closeserialbutton.setenabled(false);
  sendbutton.setenabled(false);
   }
  });
 }
 /**
  * 主菜单窗口显示;
  * 添加jlabel、按钮、下拉条及相关事件监听;
  */
 private void init() {
 
  this.setbounds(wellcomview.loc_x, wellcomview.loc_y, wellcomview.width, wellcomview.height);
  this.settitle("串口调试");
  this.seticonimage(icon);
  this.setbackground(color.gray);
  this.setlayout(null);
 
  font font =new font("微软雅黑", font.bold, 16);
 
  receivearea=new jtextarea(18, 30);
  receivearea.seteditable(false);
  jscrollpane receivescroll = new jscrollpane(receivearea);
  receivescroll.setborder(new titledborder("接收区"));
  //滚动条自动出现 fe0400030001d5c5
  receivescroll.sethorizontalscrollbarpolicy( 
  jscrollpane.horizontal_scrollbar_as_needed); 
  receivescroll.setverticalscrollbarpolicy( 
  jscrollpane.vertical_scrollbar_as_needed); 
  receivescroll.setbounds(52, 20, 680,340);
  this.add(receivescroll);
 
  jlabel chuankou=new jlabel(" 串口选择: ");
  chuankou.setfont(font);
  chuankou.setbounds(50, 380, 100,50);
  this.add(chuankou);
 
  jlabel botelv=new jlabel(" 波 特 率: ");
  botelv.setfont(font);
  botelv.setbounds(290, 380, 100,50);
  this.add(botelv);
 
  //添加串口选择选项
  commchoice = new jcombobox<string>(); //串口选择(下拉框)
  commchoice.setbounds(145, 390, 100, 30);
  this.add(commchoice);
 
  //添加波特率选项
  bpschoice = new jcombobox<string>(); //波特率选择
  bpschoice.setbounds(380, 390, 100, 30);
  bpschoice.additem("1500");
  bpschoice.additem("2400");
  bpschoice.additem("4800");
  bpschoice.additem("9600");
  bpschoice.additem("14400");
  bpschoice.additem("19500");
  bpschoice.additem("115500");
  this.add(bpschoice);
 
  //添加打开串口按钮
  openserialbutton = new jbutton("连接");
  openserialbutton.setbounds(540, 390, 80, 30);
  openserialbutton.setfont(font);
  openserialbutton.setforeground(color.darkgray);
  this.add(openserialbutton);
 
  //添加关闭串口按钮
  closeserialbutton = new jbutton("关闭");
  closeserialbutton.setenabled(false);
  closeserialbutton.setbounds(650, 390, 80, 30);
  closeserialbutton.setfont(font);
  closeserialbutton.setforeground(color.darkgray);
  this.add(closeserialbutton);
 
  sendarea=new jtextarea(30,20);
  jscrollpane sendscroll = new jscrollpane(sendarea);
  sendscroll.setborder(new titledborder("发送区"));
  //滚动条自动出现
  sendscroll.sethorizontalscrollbarpolicy( 
  jscrollpane.horizontal_scrollbar_always); 
  sendscroll.setverticalscrollbarpolicy( 
  jscrollpane.vertical_scrollbar_always); 
  sendscroll.setbounds(52, 450, 500,100);
  this.add(sendscroll);
 
  sendbutton = new jbutton("发 送");
  sendbutton.setbounds(610, 520, 120, 30);
  sendbutton.setfont(font);
  sendbutton.setforeground(color.darkgray);
  sendbutton.setenabled(false);
  this.add(sendbutton);
 
  this.setresizable(false); //窗口大小不可更改
  this.setdefaultcloseoperation(jframe.exit_on_close);
  this.setvisible(true);
 }
 
 /**字符串转16进制
  * @param hex
  * @return
  */
 private byte[] hex2byte(string hex) {
 
  string digital = "0123456789abcdef";
  string hex1 = hex.replace(" ", "");
  char[] hex2char = hex1.tochararray();
  byte[] bytes = new byte[hex1.length() / 2];
  byte temp;
  for (int p = 0; p < bytes.length; p++) {
   temp = (byte) (digital.indexof(hex2char[2 * p]) * 16);
   temp += digital.indexof(hex2char[2 * p + 1]);
   bytes[p] = (byte) (temp & 0xff);
  }
  return bytes;
 }
 /**字节数组转16进制
  * @param b
  * @return
  */
 private string printhexstring(byte[] b) {
 
  stringbuffer sbf=new stringbuffer();
  for (int i = 0; i < b.length; i++) { 
   string hex = integer.tohexstring(b[i] & 0xff); 
   if (hex.length() == 1) { 
  hex = '0' + hex; 
   } 
   sbf.append(hex.touppercase()+" ");
  }
  return sbf.tostring().trim();
 }
 /**
  * 以内部类形式创建一个串口监听类
  * @author zhong
  */
 class seriallistener implements serialporteventlistener {
 
  /**
   * 处理监控到的串口事件
   */
  public void serialevent(serialportevent serialportevent) {
 
   switch (serialportevent.geteventtype()) {
   case serialportevent.bi: // 10 通讯中断
  joptionpane.showmessagedialog(null, "与串口设备通讯中断", "错误", joptionpane.information_message);
  break;
   case serialportevent.oe: // 7 溢位(溢出)错误
  break;
   case serialportevent.fe: // 9 帧错误
  break;
   case serialportevent.pe: // 8 奇偶校验错误
  break;
   case serialportevent.cd: // 6 载波检测
  break;
   case serialportevent.cts: // 3 清除待发送数据
  break;
   case serialportevent.dsr: // 4 待发送数据准备好了
  break;
   case serialportevent.ri: // 5 振铃指示
  break;
   case serialportevent.output_buffer_empty: // 2 输出缓冲区已清空
  break;
   case serialportevent.data_available: // 1 串口存在可用数据
  string time=df.format(localdatetime.ofinstant(instant.ofepochmilli(system.currenttimemillis()),zoneid.of("asia/shanghai")));
  byte[] data;//fe0400030001d5c5
  try {
   data = serialtool.readfromport(serialport);
   receivearea.append(time+" ["+serialport.getname().split("/")[3]+"] : "+ printhexstring(data)+"\r\n");
   receivearea.setcaretposition(receivearea.gettext().length()); 
  } catch (ioexception e) {
   e.printstacktrace();
  }
  break;
   default:
  break;
   }
  }
 }
}
package serialport;
 
import java.awt.color;
import java.awt.font;
import java.awt.image;
import java.awt.toolkit;
import java.awt.event.keyadapter;
import java.awt.event.keyevent;
 
import javax.swing.jframe;
import javax.swing.jlabel;
 
 
/**
 * @author bh
 * 如果运行过程中抛出 java.lang.unsatisfiedlinkerror 错误,
 * 请将rxtx解压包中的 rxtxparallel.dll,rxtxserial.dll 这两个文件复制到 c:\windows\system32 目录下即可解决该错误。
 */
public class wellcomview {
 
 /** 程序界面宽度*/
 public static final int width = 800;
 /** 程序界面高度*/
 public static final int height = 620;
 /** 程序界面出现位置(横坐标) */
 public static final int loc_x = 200;
 /** 程序界面出现位置(纵坐标)*/
 public static final int loc_y = 70;
 
 private jframe jframe;
 
 /**主方法
  * @param args //
  */
 public static void main(string[] args) {
 
  new wellcomview();
 }
 public wellcomview() {
 
  init();
  listen();
 }
 /**
  */
 private void listen() {
 
  //添加键盘监听器
  jframe.addkeylistener(new keyadapter() {
   public void keyreleased(keyevent e) {
  int keycode = e.getkeycode();
  if (keycode == keyevent.vk_enter) { //当监听到用户敲击键盘enter键后执行下面的操作
   jframe.setvisible(false); //隐去欢迎界面
   new serialview(); //主界面类(显示监控数据主面板)
  }
   }
  }); 
 }
 /**
  * 显示主界面
  */
 private void init() {
 
  jframe=new jframe("串口调试");
  jframe.setbounds(loc_x, loc_y, width, height); //设定程序在桌面出现的位置
  jframe.setlayout(null);
  //设置window的icon(这里我自定义了一下windows窗口的icon图标,因为实在觉得哪个小咖啡图标不好看 = =)
  toolkit toolkit = jframe.gettoolkit();
  image icon = toolkit.getimage(wellcomview.class.getresource("computer.png"));
  jframe.seticonimage(icon); 
  jframe.setbackground(color.white); //设置背景色
 
  jlabel huanyin=new jlabel("欢迎使用串口调试工具");
  huanyin.setbounds(170, 80,600,50);
  huanyin.setfont(new font("微软雅黑", font.bold, 40));
  jframe.add(huanyin);
 
  jlabel banben=new jlabel("version:1.0 powered by:cyq");
  banben.setbounds(180, 390,500,50);
  banben.setfont(new font("微软雅黑", font.italic, 26));
  jframe.add(banben);
 
  jlabel enter=new jlabel("————点击enter键进入主界面————");
  enter.setbounds(100, 480,600,50);
  enter.setfont(new font("微软雅黑", font.bold, 30));
  jframe.add(enter);
 
  jframe.setresizable(false); //窗口大小不可更改
  jframe.setdefaultcloseoperation(jframe.exit_on_close);
  jframe.setvisible(true); //显示窗口
 }
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持CodeAE代码之家
原文链接:https://blog.csdn.net/cuiyaoqiang/article/details/54928627

关注下面的标签,发现更多相似文章