使用Java實現串列埠通訊
阿新 • • 發佈:2019-02-07
轉自:https://blog.csdn.net/kong_gu_you_lan/article/details/52302075
1.介紹
2.RXTXcomm
內含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();
}
}
}
- 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
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);
}
});
}
}
- 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
5.寫在最後
歡迎同學們吐槽評論,如果你覺得本篇部落格對你有用,那麼就留個言或者頂一下吧(^-^)