本文實(shí)例為大家分享了Java實(shí)現(xiàn)串口通信的具體代碼,供大家參考,具體內(nèi)容如下
1.介紹
使用Java實(shí)現(xiàn)的串口通信程序,支持十六進(jìn)制數(shù)據(jù)的發(fā)送與接收。
源碼:SerialPortDemo
效果圖如下:
2.RXTXcomm
Java串口通信依賴(lài)的jar包RXTXcomm.jar
下載地址:http://download.csdn.net/detail/kong_gu_you_lan/9611334
內(nèi)含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實(shí)現(xiàn)了對(duì)串口通信的管理,包括查找可用端口、打開(kāi)關(guān)閉串口、發(fā)送接收數(shù)據(jù)。
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
|
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 可用端口名稱(chēng)列表 */ @SuppressWarnings ( "unchecked" ) public static final ArrayList<String> findPort() { // 獲得當(dāng)前所有可用串口 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; } /** * 打開(kāi)串口 * * @param portName * 端口名稱(chēng) * @param baudrate * 波特率 * @return 串口對(duì)象 * @throws SerialPortParameterFailure * 設(shè)置串口參數(shù)失敗 * @throws NotASerialPort * 端口指向設(shè)備不是串口類(lèi)型 * @throws NoSuchPort * 沒(méi)有該端口對(duì)應(yīng)的串口設(shè)備 * @throws PortInUse * 端口已被占用 */ public static final SerialPort openPort(String portName, int baudrate) throws SerialPortParameterFailure, NotASerialPort, NoSuchPort, PortInUse { try { // 通過(guò)端口名識(shí)別端口 CommPortIdentifier portIdentifier = CommPortIdentifier .getPortIdentifier(portName); // 打開(kāi)端口,設(shè)置端口名與timeout(打開(kāi)操作的超時(shí)時(shí)間) CommPort commPort = portIdentifier.open(portName, 2000 ); // 判斷是不是串口 if (commPort instanceof SerialPort) { SerialPort serialPort = (SerialPort) commPort; try { // 設(shè)置串口的波特率等參數(shù) 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(); } } /** * 關(guān)閉串口 * * @param serialport * 待關(guān)閉的串口對(duì)象 */ public static void closePort(SerialPort serialPort) { if (serialPort != null ) { serialPort.close(); serialPort = null ; } } /** * 向串口發(fā)送數(shù)據(jù) * * @param serialPort * 串口對(duì)象 * @param order * 待發(fā)送數(shù)據(jù) * @throws SendDataToSerialPortFailure * 向串口發(fā)送數(shù)據(jù)失敗 * @throws SerialPortOutputStreamCloseFailure * 關(guān)閉串口對(duì)象的輸出流出錯(cuò) */ 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(); } } } /** * 從串口讀取數(shù)據(jù) * * @param serialPort * 當(dāng)前已建立連接的SerialPort對(duì)象 * @return 讀取到的數(shù)據(jù) * @throws ReadDataFromSerialPortFailure * 從串口讀取數(shù)據(jù)時(shí)出錯(cuò) * @throws SerialPortInputStreamCloseFailure * 關(guān)閉串口對(duì)象輸入流出錯(cuò) */ public static byte [] readFromPort(SerialPort serialPort) throws ReadDataFromSerialPortFailure, SerialPortInputStreamCloseFailure { InputStream in = null ; byte [] bytes = null ; try { in = serialPort.getInputStream(); // 獲取buffer里的數(shù)據(jù)長(zhǎng)度 int bufflenth = in.available(); while (bufflenth != 0 ) { // 初始化byte數(shù)組為buffer中數(shù)據(jù)的長(zhǎng)度 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; } /** * 添加監(jiān)聽(tīng)器 * * @param port * 串口對(duì)象 * @param listener * 串口監(jiān)聽(tīng)器 * @throws TooManyListeners * 監(jiān)聽(tīng)類(lèi)對(duì)象過(guò)多 */ public static void addListener(SerialPort port, SerialPortEventListener listener) throws TooManyListeners { try { // 給串口添加監(jiān)聽(tīng)器 port.addEventListener(listener); // 設(shè)置當(dāng)有數(shù)據(jù)到達(dá)時(shí)喚醒監(jiān)聽(tīng)接收線程 port.notifyOnDataAvailable( true ); // 設(shè)置當(dāng)通信中斷時(shí)喚醒中斷線程 port.notifyOnBreakInterrupt( true ); } catch (TooManyListenersException e) { throw new TooManyListeners(); } } } |
4.程序主窗口
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
|
/* * 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); // 串口設(shè)置面板 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("打開(kāi)串口"); private JButton sendData = new JButton("發(fā)送數(shù)據(jù)"); private List<String> commList = null; private SerialPort serialport; public MainFrame() { initView(); initComponents(); actionListener(); initData(); } private void initView() { // 關(guān)閉程序 setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); // 禁止窗口最大化 setResizable(false); // 設(shè)置程序窗口居中顯示 Point p = GraphicsEnvironment.getLocalGraphicsEnvironment() .getCenterPoint(); setBounds(p.x - WIDTH / 2, p.y - HEIGHT / 2, WIDTH, HEIGHT); this.setLayout(null); setTitle("串口通訊"); } private void initComponents() { // 數(shù)據(jù)顯示 dataView.setFocusable(false); scrollDataView.setBounds(10, 10, 475, 200); add(scrollDataView); // 串口設(shè)置 serialPortPanel.setBorder(BorderFactory.createTitledBorder("串口設(shè)置")); 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(); // 檢查是否有可用串口,有則加入選項(xiàng)中 if (commList == null || commList.size() < 1) { ShowUtils.warningMessage("沒(méi)有搜索到有效串口!"); } 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 ("打開(kāi)串口".equals(serialPortOperate.getText()) && serialport == null) { openSerialPort(e); } else { closeSerialPort(e); } } }); sendData.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { sendData(e); } }); } /** * 打開(kāi)串口 * * @param evt * 點(diǎn)擊事件 */ private void openSerialPort(java.awt.event.ActionEvent evt) { // 獲取串口名稱(chēng) String commName = (String) commChoice.getSelectedItem(); // 獲取波特率 int baudrate = 9600; String bps = (String) baudrateChoice.getSelectedItem(); baudrate = Integer.parseInt(bps); // 檢查串口名稱(chēng)是否獲取正確 if (commName == null || commName.equals("")) { ShowUtils.warningMessage("沒(méi)有搜索到有效串口!"); } else { try { serialport = SerialPortManager.openPort(commName, baudrate); if (serialport != null) { dataView.setText("串口已打開(kāi)" + "\r\n"); serialPortOperate.setText("關(guān)閉串口"); } } 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(); } } /** * 關(guān)閉串口 * * @param evt * 點(diǎn)擊事件 */ private void closeSerialPort(java.awt.event.ActionEvent evt) { SerialPortManager.closePort(serialport); dataView.setText("串口已關(guān)閉" + "\r\n"); serialPortOperate.setText("打開(kāi)串口"); } /** * 發(fā)送數(shù)據(jù) * * @param evt * 點(diǎn)擊事件 */ private void sendData(java.awt.event.ActionEvent evt) { // 輸入框直接輸入十六進(jìn)制字符,長(zhǎng)度必須是偶數(shù) 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 { /** * 處理監(jiān)控到的串口事件 */ public void serialEvent(SerialPortEvent serialPortEvent) { switch (serialPortEvent.getEventType()) { case SerialPortEvent.BI: // 10 通訊中斷 ShowUtils.errorMessage( "與串口設(shè)備通訊中斷" ); break ; case SerialPortEvent.OE: // 7 溢位(溢出)錯(cuò)誤 case SerialPortEvent.FE: // 9 幀錯(cuò)誤 case SerialPortEvent.PE: // 8 奇偶校驗(yàn)錯(cuò)誤 case SerialPortEvent.CD: // 6 載波檢測(cè) case SerialPortEvent.CTS: // 3 清除待發(fā)送數(shù)據(jù) case SerialPortEvent.DSR: // 4 待發(fā)送數(shù)據(jù)準(zhǔn)備好了 case SerialPortEvent.RI: // 5 振鈴指示 case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 2 輸出緩沖區(qū)已清空 break ; case SerialPortEvent.DATA_AVAILABLE: // 1 串口存在可用數(shù)據(jù) byte [] data = null ; try { if (serialport == null ) { ShowUtils.errorMessage( "串口對(duì)象為空!監(jiān)聽(tīng)失敗!" ); } else { // 讀取串口數(shù)據(jù) data = SerialPortManager.readFromPort(serialport); dataView.append(ByteUtils.byteArrayToHexString(data, true ) + "\r\n" ); } } catch (Exception e) { ShowUtils.errorMessage(e.toString()); // 發(fā)生讀取錯(cuò)誤時(shí)顯示錯(cuò)誤信息后退出系統(tǒng) System.exit( 0 ); } break ; } } } public static void main(String args[]) { java.awt.EventQueue.invokeLater( new Runnable() { public void run() { new MainFrame().setVisible( true ); } }); } } |
5.寫(xiě)在最后
源碼下載地址:SerialPortDemo
歡迎同學(xué)們吐槽評(píng)論,如果你覺(jué)得本篇博客對(duì)你有用,那么就留個(gè)言或者頂一下吧(^-^)
感謝:基于Java編寫(xiě)串口通信工具
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。
原文鏈接:http://blog.csdn.net/kong_gu_you_lan/article/details/52302075