国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術|正則表達式|

服務器之家 - 編程語言 - JAVA教程 - 基于Java編寫串口通信工具

基于Java編寫串口通信工具

2020-07-15 12:14Dreamer-1 JAVA教程

這篇文章主要為大家詳細介紹了基于Java編寫的一個帶有圖形界面的簡單串口通信工具,具有一定的參考價值,感興趣的小伙伴們可以參考一下

最近一門課要求編寫一個上位機串口通信工具,我基于Java編寫了一個帶有圖形界面的簡單串口通信工具,下面詳述一下過程,供大家參考 ^_^

一:

首先,你需要下載一個額外的支持Java串口通信操作的jar包,由于java.comm比較老了,而且不支持64位系統,這里推薦Rxtx這個jar包(32位/64位均支持)。

官方下載地址:http://fizzed.com/oss/rxtx-for-java (注:可能需要FQ才能下載)

不能FQ的童鞋,可以在這里下載:

javamfzrxtx.rar(32位)

javamfzrxtx.rar(64位)

二:

下載解壓jar包并在 Java Build Path 下引入:

捕獲

基于Java編寫串口通信工具

注:如果運行過程中拋出 java.lang.UnsatisfiedLinkError 錯誤,請將rxtx解壓包中的 rxtxParallel.dll,rxtxSerial.dll 這兩個文件復制到 C:\Windows\System32 目錄下即可解決該錯誤。

三:

關于該jar包的使用,我寫了一個SerialTool.java類,該類提供關于串口通信的各簡單服務,代碼如下(注意該類位于 serialPort 包里):

?
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
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.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;
import serialException.*;
 
/**
 * 串口服務類,提供打開、關閉串口,讀取、發送串口數據等服務(采用單例設計模式)
 * @author zhong
 *
 */
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 ArrayList<String> findPort() {
 
 //獲得當前所有可用串口
 Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();
 
 ArrayList<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 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();
  }
  
  //System.out.println("Open " + portName + " sucessfully !");
  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();
  int bufflenth = in.available(); //獲取buffer里的數據長度
  
  while (bufflenth != 0) {   
  bytes = new byte[bufflenth]; //初始化byte數組為buffer中數據的長度
  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();
 }
 }
 
 
}

注:該類方法中 throw 的 Exception 都是我自定義的 Exception,之所以這么做是為了方便在主程序中進行相應處理,下面貼其中一個Exception出來給大家做下說明:

(注意我所有自定義的 Exception 都放在 serialException 包里)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package serialException;
 
public class SerialPortParameterFailure extends Exception {
 /**
 *
 */
 private static final long serialVersionUID = 1L;
 
 public SerialPortParameterFailure() {}
 
 @Override
 public String toString() {
 return "設置串口參數失敗!打開串口操作未完成!";
 }
 
}

每個自定義的Exception類我都重寫了它的 toString() 方法,便于主程序捕捉到該Exception后打印對應的錯誤信息

其中在serialException包里還有一個專門將接收到的Exception對象內的錯誤信息提取出來轉換成字符串并返回的類,代碼如下:

?
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
package serialException;
 
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
 
/**
 * 負責將傳入的Exception中的錯誤信息提取出來并轉換成字符串;
 * @author zhong
 *
 */
public class ExceptionWriter {
 
 /**
 * 將Exception中的錯誤信息封裝到字符串中并返回該字符串
 * @param e 包含錯誤的Exception
 * @return 錯誤信息字符串
 */
 public static String getErrorInfoFromException(Exception e) {
  
  StringWriter sw = null;
  PrintWriter pw = null;
  
  try {
  sw = new StringWriter();
  pw = new PrintWriter(sw);
  e.printStackTrace(pw);
  return "\r\n" + sw.toString() + "\r\n";
  
  } catch (Exception e2) {
  return "出錯啦!未獲取到錯誤信息,請檢查后重試!";
  } finally {
  try {
   if (pw != null) {
   pw.close();
   }
   if (sw != null) {
   sw.close();
   }
  } catch (IOException e1) {
   e1.printStackTrace();
  }
  }
 }
}

四:

主程序類的使用,Client.java里含有程序的入口地址(main方法),它的作用是顯示一個歡迎界面并調用DataView.java這個類進行實際的串口數據顯示。

Client.java代碼如下:

?
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
package serialPort;
 
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Label;
import java.awt.Panel;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
 
import javax.swing.JOptionPane;
 
import serialException.ExceptionWriter;
 
/**
 * 主程序
 * @author zhong
 *
 */
public class Client extends Frame{
 
 /**
 *
 */
 private static final long serialVersionUID = 1L;
 
 /**
 * 程序界面寬度
 */
 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;
 
 Color color = Color.WHITE;
 Image offScreen = null; //用于雙緩沖
 
 //設置window的icon(這里我自定義了一下Windows窗口的icon圖標,因為實在覺得哪個小咖啡圖標不好看 = =)
 Toolkit toolKit = getToolkit();
 Image icon = toolKit.getImage(Client.class.getResource("computer.png"));
 
 //持有其他類
 DataView dataview = new DataView(this); //主界面類(顯示監控數據主面板)
 
 /**
 * 主方法
 * @param args //
 */
 public static void main(String[] args) {
 new Client().launchFrame();
 }
 
 /**
 * 顯示主界面
 */
 public void launchFrame() {
 this.setBounds(LOC_X, LOC_Y, WIDTH, HEIGHT); //設定程序在桌面出現的位置
 this.setTitle("CDIO工程項目"); //設置程序標題
 this.setIconImage(icon);
 this.setBackground(Color.white); //設置背景色
 
 this.addWindowListener(new WindowAdapter() {
  //添加對窗口狀態的監聽
  public void windowClosing(WindowEvent arg0) {
  //當窗口關閉時
  System.exit(0); //退出程序
  }
  
 });
 
 this.addKeyListener(new KeyMonitor()); //添加鍵盤監聽器
 this.setResizable(false); //窗口大小不可更改
 this.setVisible(true); //顯示窗口
  
 new Thread(new RepaintThread()).start(); //開啟重畫線程
 }
 
 /**
 * 畫出程序界面各組件元素
 */
 public void paint(Graphics g) {
 Color c = g.getColor();
 
 g.setFont(new Font("微軟雅黑", Font.BOLD, 40));
 g.setColor(Color.black);
 g.drawString("歡迎使用上位機實時監控系統", 45, 190);
 
 g.setFont(new Font("微軟雅黑", Font.ITALIC, 26));
 g.setColor(Color.BLACK);
 g.drawString("Version:1.0 Powered By:ZhongLei", 280, 260);
 
 g.setFont(new Font("微軟雅黑", Font.BOLD, 30));
 g.setColor(color);
 g.drawString("————點擊Enter鍵進入主界面————", 100, 480);
 //使文字 "————點擊Enter鍵進入主界面————" 黑白閃爍
 if (color == Color.WHITE) color = Color.black;
 else if (color == color.BLACK) color = Color.white;
 
 
 }
 
 /**
 * 雙緩沖方式重畫界面各元素組件
 */
 public void update(Graphics g) {
 if (offScreen == null) offScreen = this.createImage(WIDTH, HEIGHT);
 Graphics gOffScreen = offScreen.getGraphics();
 Color c = gOffScreen.getColor();
 gOffScreen.setColor(Color.white);
 gOffScreen.fillRect(0, 0, WIDTH, HEIGHT); //重畫背景畫布
 this.paint(gOffScreen); //重畫界面元素
 gOffScreen.setColor(c);
 g.drawImage(offScreen, 0, 0, null); //將新畫好的畫布“貼”在原畫布上
 }
 
 /*
 * 內部類形式實現對鍵盤事件的監聽
 */
 private class KeyMonitor extends KeyAdapter {
 
 public void keyReleased(KeyEvent e) {
  int keyCode = e.getKeyCode();
  if (keyCode == KeyEvent.VK_ENTER) { //當監聽到用戶敲擊鍵盤enter鍵后執行下面的操作
  setVisible(false); //隱去歡迎界面
  dataview.setVisible(true); //顯示監測界面
  dataview.dataFrame(); //初始化監測界面
  }
 }
 
 }
 
 
 /*
 * 重畫線程(每隔250毫秒重畫一次)
 */
 private class RepaintThread implements Runnable {
 public void run() {
  while(true) {
  repaint();
  try {
   Thread.sleep(250);
  } catch (InterruptedException e) {
   //重畫線程出錯拋出異常時創建一個Dialog并顯示異常詳細信息
   String err = ExceptionWriter.getErrorInfoFromException(e);
   JOptionPane.showMessageDialog(null, err, "錯誤", JOptionPane.INFORMATION_MESSAGE);
   System.exit(0);
  }
  }
 }
 
 }
 
}

運行截圖:

注:實際運行過程中最下面的“點擊Enter鍵進入主界面”有一個一閃一閃的效果(是通過每隔一段時間重畫一次界面,讓這句話以白黑兩色反復交替出現實現的),雙緩沖方式利于解決重畫時界面閃爍的問題(如果不使用雙緩沖方式的話相當于每次重畫時是在舊界面上一點一點畫上新東西,而雙緩沖實質上是通過先在內存中直接畫好一張新界面圖,然后一次性直接用新界面覆蓋掉舊界面)

基于Java編寫串口通信工具

DataView.java代碼如下:(該類用于實時顯示串口數據)

簡單說明:

硬件設備每隔一段時間通過串口發送一次數據到計算機,該串口工具成功連接至硬件設備并添加監聽后,會在每次接收到數據時解析數據并更新界面;

你在使用時很可能需求跟我不一樣,該類僅供參考,實際使用中你很可能需要重新制作數據顯示界面以及數據解析方式

?
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
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
package serialPort;
 
import java.awt.Button;
import java.awt.Choice;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Label;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.List;
import java.util.TooManyListenersException;
 
import javax.swing.JOptionPane;
 
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import serialException.*;
 
/**
 * 監測數據顯示類
 * @author Zhong
 *
 */
public class DataView extends Frame {
 
 /**
 *
 */
 private static final long serialVersionUID = 1L;
 
 Client client = null;
 
 private List<String> commList = null; //保存可用端口號
 private SerialPort serialPort = null; //保存串口對象
 
 private Font font = new Font("微軟雅黑", Font.BOLD, 25);
 
 private Label tem = new Label("暫無數據", Label.CENTER); //溫度
 private Label hum = new Label("暫無數據", Label.CENTER); //濕度
 private Label pa = new Label("暫無數據", Label.CENTER); //壓強
 private Label rain = new Label("暫無數據", Label.CENTER); //雨量
 private Label win_sp = new Label("暫無數據", Label.CENTER); //風速
 private Label win_dir = new Label("暫無數據", Label.CENTER); //風向
 
 private Choice commChoice = new Choice(); //串口選擇(下拉框)
 private Choice bpsChoice = new Choice(); //波特率選擇
 
 private Button openSerialButton = new Button("打開串口");
 
 Image offScreen = null; //重畫時的畫布
 
 //設置window的icon
 Toolkit toolKit = getToolkit();
 Image icon = toolKit.getImage(DataView.class.getResource("computer.png"));
 
 /**
 * 類的構造方法
 * @param client
 */
 public DataView(Client client) {
 this.client = client;
 commList = SerialTool.findPort(); //程序初始化時就掃描一次有效串口
 }
 
 /**
 * 主菜單窗口顯示;
 * 添加Label、按鈕、下拉條及相關事件監聽;
 */
 public void dataFrame() {
 this.setBounds(client.LOC_X, client.LOC_Y, client.WIDTH, client.HEIGHT);
 this.setTitle("CDIO工程項目");
 this.setIconImage(icon);
 this.setBackground(Color.white);
 this.setLayout(null);
 
 this.addWindowListener(new WindowAdapter() {
  public void windowClosing(WindowEvent arg0) {
  if (serialPort != null) {
   //程序退出時關閉串口釋放資源
   SerialTool.closePort(serialPort);
  }
  System.exit(0);
  }
  
 });
 
 tem.setBounds(140, 103, 225, 50);
 tem.setBackground(Color.black);
 tem.setFont(font);
 tem.setForeground(Color.white);
 add(tem);
 
 hum.setBounds(520, 103, 225, 50);
 hum.setBackground(Color.black);
 hum.setFont(font);
 hum.setForeground(Color.white);
 add(hum);
 
 pa.setBounds(140, 193, 225, 50);
 pa.setBackground(Color.black);
 pa.setFont(font);
 pa.setForeground(Color.white);
 add(pa);
 
 rain.setBounds(520, 193, 225, 50);
 rain.setBackground(Color.black);
 rain.setFont(font);
 rain.setForeground(Color.white);
 add(rain);
 
 win_sp.setBounds(140, 283, 225, 50);
 win_sp.setBackground(Color.black);
 win_sp.setFont(font);
 win_sp.setForeground(Color.white);
 add(win_sp);
 
 win_dir.setBounds(520, 283, 225, 50);
 win_dir.setBackground(Color.black);
 win_dir.setFont(font);
 win_dir.setForeground(Color.white);
 add(win_dir);
 
 //添加串口選擇選項
 commChoice.setBounds(160, 397, 200, 200);
 //檢查是否有可用串口,有則加入選項中
 if (commList == null || commList.size()<1) {
  JOptionPane.showMessageDialog(null, "沒有搜索到有效串口!", "錯誤", JOptionPane.INFORMATION_MESSAGE);
 }
 else {
  for (String s : commList) {
  commChoice.add(s);
  }
 }
 add(commChoice);
 
 //添加波特率選項
 bpsChoice.setBounds(526, 396, 200, 200);
 bpsChoice.add("1200");
 bpsChoice.add("2400");
 bpsChoice.add("4800");
 bpsChoice.add("9600");
 bpsChoice.add("14400");
 bpsChoice.add("19200");
 bpsChoice.add("115200");
 add(bpsChoice);
 
 //添加打開串口按鈕
 openSerialButton.setBounds(250, 490, 300, 50);
 openSerialButton.setBackground(Color.lightGray);
 openSerialButton.setFont(new Font("微軟雅黑", Font.BOLD, 20));
 openSerialButton.setForeground(Color.darkGray);
 add(openSerialButton);
 //添加打開串口按鈕的事件監聽
 openSerialButton.addActionListener(new ActionListener() {
 
  public void actionPerformed(ActionEvent e) {
  
  //獲取串口名稱
  String commName = commChoice.getSelectedItem(); 
  //獲取波特率
  String bpsStr = 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());
    //監聽成功進行提示
    JOptionPane.showMessageDialog(null, "監聽成功,稍后將顯示監測數據!", "提示", JOptionPane.INFORMATION_MESSAGE);
    
   } catch (SerialPortParameterFailure | NotASerialPort | NoSuchPort | PortInUse | TooManyListeners e1) {
    //發生錯誤時使用一個Dialog提示具體的錯誤信息
    JOptionPane.showMessageDialog(null, e1, "錯誤", JOptionPane.INFORMATION_MESSAGE);
   }
   }
  }
  
  }
 });
 
 
 this.setResizable(false);
 
 new Thread(new RepaintThread()).start(); //啟動重畫線程
 
 }
 
 /**
 * 畫出主界面組件元素
 */
 public void paint(Graphics g) {
 Color c = g.getColor();
 
 g.setColor(Color.black);
 g.setFont(new Font("微軟雅黑", Font.BOLD, 25));
 g.drawString(" 溫度: ", 45, 130);
 
 g.setColor(Color.black);
 g.setFont(new Font("微軟雅黑", Font.BOLD, 25));
 g.drawString(" 濕度: ", 425, 130);
 
 g.setColor(Color.black);
 g.setFont(new Font("微軟雅黑", Font.BOLD, 25));
 g.drawString(" 壓強: ", 45, 220);
 
 g.setColor(Color.black);
 g.setFont(new Font("微軟雅黑", Font.BOLD, 25));
 g.drawString(" 雨量: ", 425, 220);
 
 g.setColor(Color.black);
 g.setFont(new Font("微軟雅黑", Font.BOLD, 25));
 g.drawString(" 風速: ", 45, 310);
 
 g.setColor(Color.black);
 g.setFont(new Font("微軟雅黑", Font.BOLD, 25));
 g.drawString(" 風向: ", 425, 310);
 
 g.setColor(Color.gray);
 g.setFont(new Font("微軟雅黑", Font.BOLD, 20));
 g.drawString(" 串口選擇: ", 45, 410);
 
 g.setColor(Color.gray);
 g.setFont(new Font("微軟雅黑", Font.BOLD, 20));
 g.drawString(" 波特率: ", 425, 410);
 
 }
 
 /**
 * 雙緩沖方式重畫界面各元素組件
 */
 public void update(Graphics g) {
 if (offScreen == null) offScreen = this.createImage(Client.WIDTH, Client.HEIGHT);
 Graphics gOffScreen = offScreen.getGraphics();
 Color c = gOffScreen.getColor();
 gOffScreen.setColor(Color.white);
 gOffScreen.fillRect(0, 0, Client.WIDTH, Client.HEIGHT); //重畫背景畫布
 this.paint(gOffScreen); //重畫界面元素
 gOffScreen.setColor(c);
 g.drawImage(offScreen, 0, 0, null); //將新畫好的畫布“貼”在原畫布上
 }
 
 /*
 * 重畫線程(每隔30毫秒重畫一次)
 */
 private class RepaintThread implements Runnable {
 public void run() {
  while(true) {
  //調用重畫方法
  repaint();
  
  
  
  //掃描可用串口
  commList = SerialTool.findPort();
  if (commList != null && commList.size()>0) {
   
   //添加新掃描到的可用串口
   for (String s : commList) {
   
   //該串口名是否已存在,初始默認為不存在(在commList里存在但在commChoice里不存在,則新添加)
   boolean commExist = false;
   
   for (int i=0; i<commChoice.getItemCount(); i++) {
    if (s.equals(commChoice.getItem(i))) {
    //當前掃描到的串口名已經在初始掃描時存在
    commExist = true;
    break;
    }  
   }
   
   if (commExist) {
    //當前掃描到的串口名已經在初始掃描時存在,直接進入下一次循環
    continue;
   }
   else {
    //若不存在則添加新串口名至可用串口下拉列表
    commChoice.add(s);
   }
   }
   
   //移除已經不可用的串口
   for (int i=0; i<commChoice.getItemCount(); i++) {
   
   //該串口是否已失效,初始默認為已經失效(在commChoice里存在但在commList里不存在,則已經失效)
   boolean commNotExist = true;
   
   for (String s : commList) {
    if (s.equals(commChoice.getItem(i))) {
    commNotExist = false;
    break;
    }
   }
   
   if (commNotExist) {
    //System.out.println("remove" + commChoice.getItem(i));
    commChoice.remove(i);
   }
   else {
    continue;
   }
   }
   
  }
  else {
   //如果掃描到的commList為空,則移除所有已有串口
   commChoice.removeAll();
  }
 
  try {
   Thread.sleep(30);
  } catch (InterruptedException e) {
   String err = ExceptionWriter.getErrorInfoFromException(e);
   JOptionPane.showMessageDialog(null, err, "錯誤", JOptionPane.INFORMATION_MESSAGE);
   System.exit(0);
  }
  }
 }
 
 }
 
 /**
 * 以內部類形式創建一個串口監聽類
 * @author zhong
 *
 */
 private 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 溢位(溢出)錯誤
 
  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 串口存在可用數據
   
   //System.out.println("found data");
   byte[] data = null;
   
   try {
   if (serialPort == null) {
    JOptionPane.showMessageDialog(null, "串口對象為空!監聽失敗!", "錯誤", JOptionPane.INFORMATION_MESSAGE);
   }
   else {
    data = SerialTool.readFromPort(serialPort); //讀取數據,存入字節數組
    //System.out.println(new String(data));
    
   // 自定義解析過程,你在實際使用過程中可以按照自己的需求在接收到數據后對數據進行解析
    if (data == null || data.length < 1) { //檢查數據是否讀取正確
    JOptionPane.showMessageDialog(null, "讀取數據過程中未獲取到有效數據!請檢查設備或程序!", "錯誤", JOptionPane.INFORMATION_MESSAGE);
    System.exit(0);
    }
    else {
    String dataOriginal = new String(data); //將字節數組數據轉換位為保存了原始數據的字符串
    String dataValid = ""; //有效數據(用來保存原始數據字符串去除最開頭*號以后的字符串)
    String[] elements = null; //用來保存按空格拆分原始字符串后得到的字符串數組
    //解析數據
    if (dataOriginal.charAt(0) == '*') { //當數據的第一個字符是*號時表示數據接收完成,開始解析   
     dataValid = dataOriginal.substring(1);
     elements = dataValid.split(" ");
     if (elements == null || elements.length < 1) { //檢查數據是否解析正確
     JOptionPane.showMessageDialog(null, "數據解析過程出錯,請檢查設備或程序!", "錯誤", JOptionPane.INFORMATION_MESSAGE);
     System.exit(0);
     }
     else {
     try {
      //更新界面Label值
      /*for (int i=0; i<elements.length; i++) {
      System.out.println(elements[i]);
      }*/
      //System.out.println("win_dir: " + elements[5]);
      tem.setText(elements[0] + " ℃");
      hum.setText(elements[1] + " %");
      pa.setText(elements[2] + " hPa");
      rain.setText(elements[3] + " mm");
      win_sp.setText(elements[4] + " m/s");
      win_dir.setText(elements[5] + " °");
     } catch (ArrayIndexOutOfBoundsException e) {
      JOptionPane.showMessageDialog(null, "數據解析過程出錯,更新界面數據失敗!請檢查設備或程序!", "錯誤", JOptionPane.INFORMATION_MESSAGE);
      System.exit(0);
     }
     }
    }
    }
    
   }  
   
   } catch (ReadDataFromSerialPortFailure | SerialPortInputStreamCloseFailure e) {
   JOptionPane.showMessageDialog(null, e, "錯誤", JOptionPane.INFORMATION_MESSAGE);
   System.exit(0); //發生讀取錯誤時顯示錯誤信息后退出系統
   }
   
   break;
 
  }
 
 }
 
 }
 
 
}

運行截圖:

基于Java編寫串口通信工具

基于Java編寫串口通信工具

整個項目源碼打包下載:javaserialMonitor.rar

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 日韩欧美手机在线 | 久久久免费精品视频 | 成人精品国产免费网站 | 国产一区二区精品 | 亚洲在线视频一区二区 | 日日操视频| 亚洲精品成人 | 国产精品一区二区不卡 | 精品国产一区二区三区久久久蜜 | 成人永久免费视频 | 精品国产成人在线 | 亚洲国产精品久久久久久 | 欧美 日韩 中文字幕 | 亚洲人一区二区 | 成人午夜影院 | 中文字幕乱码亚洲无线三区 | 天天综合网网欲色 | 中文字幕在线观看第一页 | 日日夜夜视频 | 亚洲淫片 | 欧美一级免费 | 我要看日本黄色小视频 | 狠狠操狠狠操 | 久久久精品国产亚洲 | 一级黄色免费毛片 | 午夜免费视频 | 国产成人av在线播放 | 国产精品美乳一区二区免费 | 6080夜射猫 | 国产免费视频在线 | 国产精品网站在线观看 | 免费成人在线观看视频 | 欧美一区二区三区在线 | 国产精品美女www爽爽爽软件 | 久久麻豆| 黄色在线不卡 | 成人精品一区二区三区 | 亚洲视频 中文字幕 | 午夜伦理影院 | 国产日韩精品一区二区 | 免费福利视频一区二区三区 |