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

时间:2022-01-21 08:12:01

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

最终效果如下图:

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

1、把rxtxparallel.dll、rxtxserial.dll拷贝到:c:\windows\system32下。
2、rxtxcomm.jar 添加到项目类库中。

代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
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);
 }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
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;
   }
  }
 }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
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); //显示窗口
 }
}

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

原文链接:https://blog.csdn.net/cuiyaoqiang/article/details/54928627