JAVA 用 JSerialComm 读串口数据
1. MAVEN 添加 JSerialComm 依赖
<!-- java 操作串口包2 -->
<dependency>
<groupId>com.fazecast</groupId>
<artifactId>jSerialComm</artifactId>
<version>[2.0.0,3.0.0)</version>
</dependency>
2. 编写测试类
重要:串口打开后和两次读取之间一定要休眠,不然程序感知不到输入流里有数据!
package com.yhf.serialcommtest.test;//改成你自己的包
import com.fazecast.jSerialComm.SerialPort;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
/**
* @author yhf
* @Email 1713139648@qq.com
* @since 2022-04-26 9:18
*/
public class WeightTest {
public static void main(String[] args) {
SerialPort[] serialPorts = SerialPort.getCommPorts();
SerialPort com3 = null;
for (SerialPort serialPort : serialPorts) {
System.out.println("isOpen="+serialPort.isOpen());
System.out.println("SystemPortPath="+serialPort.getSystemPortPath());
System.out.println("SystemPortName="+serialPort.getSystemPortName());
if("COM3".equals(serialPort.getSystemPortName())){
com3 = serialPort;
}
System.out.println("DescriptivePortName="+serialPort.getDescriptivePortName());
System.out.println("PortDescription="+serialPort.getPortDescription());
System.out.println("PortLocation="+serialPort.getPortLocation());
System.out.println("BaudRate="+serialPort.getBaudRate());
System.out.println("CTS="+serialPort.getCTS());
System.out.println("DCD="+serialPort.getDCD());
System.out.println("DeviceReadBufferSize="+serialPort.getDeviceReadBufferSize());
System.out.println("DeviceWriteBufferSize="+serialPort.getDeviceWriteBufferSize());
System.out.println("DSR="+serialPort.getDSR());
System.out.println("DTR="+serialPort.getDTR());
System.out.println("FlowControlSettings="+serialPort.getFlowControlSettings());
System.out.println("LastErrorCode="+serialPort.getLastErrorCode());
System.out.println("LastErrorLocation="+serialPort.getLastErrorLocation());
System.out.println("NumDataBits="+serialPort.getNumDataBits());
System.out.println("NumStopBits="+serialPort.getNumStopBits());
System.out.println("Parity="+serialPort.getParity());
System.out.println("ReadTimeout="+serialPort.getReadTimeout());
System.out.println("RI="+serialPort.getRI());
System.out.println("RTS="+serialPort.getRTS());
System.out.println("WriteTimeout="+serialPort.getWriteTimeout());
System.out.println("*************************************************************");
}
if (com3 == null){
throw new NullPointerException("未找到COM3");
}
com3.setParity(SerialPort.EVEN_PARITY);//偶校验
com3.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED);//关闭流控
boolean b = com3.openPort();
if (b){
InputStream inputStream = com3.getInputStream();
try {
Thread.sleep(1000);//打开串口后要休眠一段时间才能接收到输入流
System.out.println(com3.getSystemPortName()+"成功开启");
int available = inputStream.available();
System.out.println(com3.getSystemPortName()+"可读字节:"+available);
while (inputStream.available() > 0){
byte[] bytes = new byte[1024];
int read = inputStream.read(bytes);
System.out.println("读取:"+read+"字节");
System.out.println(Arrays.toString(bytes));
Thread.sleep(1000);//要休眠一段时间才能感知下一波数据
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
} finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
com3.closePort();
}
}
}
}
3. 不用 while 循环,用监听器监听串口数据变化:
public static void testDataListener(String[] args) {
SerialPort[] serialPorts = SerialPort.getCommPorts();
SerialPort com1 = null;
for (SerialPort serialPort : serialPorts) {
System.out.println("isOpen="+serialPort.isOpen());
System.out.println("SystemPortPath="+serialPort.getSystemPortPath());
System.out.println("SystemPortName="+serialPort.getSystemPortName());
if("COM1".equals(serialPort.getSystemPortName())){
com1 = serialPort;
}
System.out.println("DescriptivePortName="+serialPort.getDescriptivePortName());
System.out.println("PortDescription="+serialPort.getPortDescription());
System.out.println("PortLocation="+serialPort.getPortLocation());
System.out.println("BaudRate="+serialPort.getBaudRate());
System.out.println("CTS="+serialPort.getCTS());
System.out.println("DCD="+serialPort.getDCD());
System.out.println("DeviceReadBufferSize="+serialPort.getDeviceReadBufferSize());
System.out.println("DeviceWriteBufferSize="+serialPort.getDeviceWriteBufferSize());
System.out.println("DSR="+serialPort.getDSR());
System.out.println("DTR="+serialPort.getDTR());
System.out.println("FlowControlSettings="+serialPort.getFlowControlSettings());
System.out.println("LastErrorCode="+serialPort.getLastErrorCode());
System.out.println("LastErrorLocation="+serialPort.getLastErrorLocation());
System.out.println("NumDataBits="+serialPort.getNumDataBits());
System.out.println("NumStopBits="+serialPort.getNumStopBits());
System.out.println("Parity="+serialPort.getParity());
System.out.println("ReadTimeout="+serialPort.getReadTimeout());
System.out.println("RI="+serialPort.getRI());
System.out.println("RTS="+serialPort.getRTS());
System.out.println("WriteTimeout="+serialPort.getWriteTimeout());
System.out.println("*************************************************************");
}
if (com1 == null){
throw new NullPointerException("未找到COM1");
}
com1.setParity(SerialPort.EVEN_PARITY);//偶校验
com1.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED);//关闭流控
boolean b = com1.openPort();
if (b){
try {
Thread.sleep(1000);//打开串口后要休眠一段时间才能接收到输入流
SerialPort finalCom = com1;
com1.addDataListener(new SerialPortDataListener() {
@Override
public int getListeningEvents() {
return SerialPort.LISTENING_EVENT_DATA_AVAILABLE;//返回要监听的事件类型,以供回调函数使用。可发回的事件包括:SerialPort.LISTENING_EVENT_DATA_AVAILABLE,SerialPort.LISTENING_EVENT_DATA_WRITTEN,SerialPort.LISTENING_EVENT_DATA_RECEIVED。分别对应有数据在串口(不论是读的还是写的),有数据写入串口,从串口读取数据。如果AVAILABLE和RECEIVED同时被监听,优先触发RECEIVED
}
@Override
public void serialEvent(SerialPortEvent event) {
if (event.getEventType() != SerialPort.LISTENING_EVENT_DATA_AVAILABLE){
return;//判断事件的类型
}
//同样使用循环读取法读取所有数据
while(finalCom.bytesAvailable()!=0) {
byte[] newData = new byte[finalCom.bytesAvailable()];
int numRead = finalCom.readBytes(newData, newData.length);
System.out.println(finalCom.getSystemPortName()+"接收到字节数:"+numRead);
System.out.println(finalCom.getSystemPortName()+"数据:"+Arrays.toString(newData));
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
监听器可以一直监听串口,适合实时的数据抓取,而且不用 while 循环空转: