最近在做传感器数据采集的工作,底层是基于Zigbee的无线传感网络,所有数据采集到Zigbee协调器上然后通知上位机数据采集完成,上位机通过USB转串口去读取数据就可以了。那么问题来了,如何进行串口通讯呢?老板说你用Java写个程序好了嘛,用Java写串口程序也是醉了。实验室也没别人写了,所以就让我写了。当我听到要让我用Java写串口通讯程序的时候我本来是拒绝的,然后。。。就没有然后了。。就只能写了。
网上看了一下,最后用了一个开源的Java串口通讯库RXTX做串口通讯,下面记录一下RXTX的使用方法。
环境配置
RXTX做串口通讯,有一个jar包(RXTXcomm.jar)和一个rxtxSerial.dll(Windows环境下)或者librxtxSerial.so(Linux环境下),因为开发是在Windows上,但是工作是在Linux上,所以两个都用到了。
Windows环境下
文档里是这么写的
Copy rxtxSerial.dll —> \jre\bin
但是这个做了之后并不能用,会有一些很奇怪的问题,不知道是不是我的Java环境配置有问题还是怎么了,我是把dll文件copy到了C:\Windows\System32,然后一切正常,一直很奇怪,为什么要cp到\jre\bin呢?求解答!
Linux环境下
Copy librxtxSerial.so —> /jre/lib/i386/
or
Copy librxtxSerial.so —> /jre/lib/x86_64/
这个按照文档没问题。
小问题
我用的是rxtx-2.2pre2版本的,文档里有写运行时会报版本不匹配的WARNING,实际使用中的确也是这样的,不过目前还没有别的问题,不影响使用。
常用方法
1.查找端口
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
|
public static final ArrayList<String> findPort() {
Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();
ArrayList<String> portNameList = new ArrayList<>();
while (portList.hasMoreElements()) {
String portName = portList.nextElement().getName();
portNameList.add(portName);
}
return portNameList;
}
|
2.打开端口
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
|
public static final SerialPort openPort(String portName, int baudrate) {
try {
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
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) {
LOGGER.error("Set Serialport Parameters failure", e);
}
System.out.println("Open " + portName + " sucessfully !");
return serialPort;
} else {
LOGGER.error("This port is not a serialport");
return null;
}
} catch (NoSuchPortException | PortInUseException e) {
LOGGER.error("There is no " + portName + "or it's occupied!", e);
return null;
}
}
|
3.发送数据
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
|
public void sendToPort(SerialPort serialPort, byte[] order) {
try {
OutputStream out = serialPort.getOutputStream();
out.write(order);
out.flush();
out.close();
} catch (IOException e) {
LOGGER.error("Send to SerialPort failure", e);
}
}
|
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
|
public byte[] readFromPort(InputStream inStream) {
byte[] bytes = null;
try {
while (true) {
int bufflenth = inStream.available();
if (0 == bufflenth) {
break;
}
bytes = new byte[bufflenth];
inStream.read(bytes);
}
} catch (IOException e) {
LOGGER.error("Read Data Failure", e);
}
return bytes;
}
|
监听器
1.实现监听器
继承SerialPortEventListener然后重写serialEvent,然后再各个对应case里面写代码就好啦。
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
| public class TestExample implements SerialPortEventListener {
@Override
public void serialEvent(SerialPortEvent serialPortEvent) {
switch (serialPortEvent.getEventType()) {
case SerialPortEvent.BI:
case SerialPortEvent.OE:
case SerialPortEvent.FE:
case SerialPortEvent.PE:
case SerialPortEvent.CD:
case SerialPortEvent.CTS:
case SerialPortEvent.DSR:
case SerialPortEvent.RI:
case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
case SerialPortEvent.DATA_AVAILABLE:
}
}
}
|
2.给串口添加监听器
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
|
public static void addListener(SerialPort port, SerialPortEventListener listener) {
try {
port.addEventListener(listener);
port.notifyOnDataAvailable(true);
port.notifyOnBreakInterrupt(true);
System.out.println("Add listeners to " + port.getName() + " sucessfully !");
} catch (TooManyListenersException e) {
LOGGER.error("There is too many listeners !", e);
}
}
|
TIP
** 一定记得从串口发指令取数据之后加一个延时,等待底层数据传输完成再去buffer里面取,不然很大可能数据包不完整。 **