准备工作
1.下载
地址: http://fizzed.com/oss/rxtx-for-java
这里的下载是根据jdk安装的位数下载,我之前下载的是W64的版本,电脑系统也是64的,但是代码跑不起来,后来才发现我电脑的JDK是32位的。
2、
下载完成后将 rxtxParallel.dll 、 rxtxSerial.dll 、文件拷贝到放入<JAVA_HOME>\jre\bin中
3、Maven
方式一: 本地jar包直接引入
<dependency>
<groupId>com.test</groupId>
<artifactId>rxtxcomm</artifactId>
<version>2.2</version>
<scope>system</scope>
<systemPath>${basedir}/lib/RXTXcomm.jar</systemPath>
</dependency>
方式二 : maven引入
<dependency>
<groupId>org.bidib.jbidib.org.qbang.rxtx</groupId>
<artifactId>rxtxcomm</artifactId>
<version>2.2</version>
</dependency>
代码
public class SerialPortUtil implements SerialPortEventListener {
private static final Logger log = LoggerFactory.getLogger(SerialPortUtil.class);
// 串口对象引用
static SerialPort serialPort;
// 堵塞队列:用来存放串口发送到服务端的数据
public BlockingQueue<String> msgQueue = new LinkedBlockingQueue();
// 线程控制标识
public static boolean flag = true;
/**
* 关闭串口
*
* @param serialPort 要关闭的串口对象
*/
public void closeSerialPort(SerialPort serialPort) {
if (serialPort != null) {
serialPort.close();
}
}
/**
* 给串口设置监听
*
* @param serialPort serialPort 要读取的串口
* @param listener SerialPortEventListener监听对象
* @throws TooManyListenersException 监听对象太多
*/
public void setListenerToSerialPort(SerialPort serialPort, SerialPortEventListener listener) throws TooManyListenersException {
//给串口添加事件监听
serialPort.addEventListener(listener);
//串口有数据监听
serialPort.notifyOnDataAvailable(true);
//中断事件监听
serialPort.notifyOnBreakInterrupt(true);
log.debug("给串口添加事件监听");
}
/**
* 关闭监听
*
* @param port
*/
public void removeListener(SerialPort port) {
port.notifyOnRingIndicator(false);
port.notifyOnParityError(false);
port.notifyOnOverrunError(false);
port.notifyOnOutputEmpty(false);
port.notifyOnFramingError(false);
port.notifyOnDSR(false);
port.notifyOnDataAvailable(false);
port.notifyOnCTS(false);
port.notifyOnCarrierDetect(false);
port.notifyOnBreakInterrupt(false);
port.removeEventListener();
}
/**
* 从串口读取数据
*
* @param serialPort 要读取的串口
* @return 读取的数据
*/
public byte[] readData(SerialPort serialPort) {
InputStream is = null;
byte[] bytes = null;
try {
//获得串口的输入流
is = serialPort.getInputStream();
//获得数据长度
int bufflenth = is.available();
while (bufflenth != 0) {
//初始化byte数组
bytes = new byte[bufflenth];
is.read(bytes);
bufflenth = is.available();
}
} catch (IOException e) {
log.error("串口断开关闭监听");
removeListener(serialPort);
closeSerialPort(serialPort);
} finally {
try {
if (is != null) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return bytes;
}
/**
* 查找电脑上所有可用 com 端口
*
* @return 可用端口名称列表,没有时 列表为空
*/
public final ArrayList<String> findSystemAllComPort() {
/**
* getPortIdentifiers:获得电脑主板当前所有可用串口
*/
Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();
ArrayList<String> portNameList = new ArrayList<>();
/**
* 将可用串口名添加到 List 列表
*/
while (portList.hasMoreElements()) {
String portName = portList.nextElement().getName();//名称如 COM1、COM2....
portNameList.add(portName);
}
return portNameList;
}
/**
* 打开电脑上指定的串口
*
* @param portName 端口名称,如 COM1,为 null 时,默认使用电脑中能用的端口中的第一个
* @param b 波特率(baudrate),如 9600
* @param d 数据位(datebits),如 SerialPort.DATABITS_8 = 8
* @param s 停止位(stopbits),如 SerialPort.STOPBITS_1 = 1
* @param p 校验位 (parity),如 SerialPort.PARITY_NONE = 0
* @return 打开的串口对象,打开失败时,返回 null
*/
public final SerialPort openSerialPort(String portName, int b, int d, int s, int p) {
CommPort commPort = null;
try {
//当没有传入可用的 com 口时,默认使用电脑中可用的 com 口中的第一个
if (StringUtils.isEmpty(portName)) {
List<String> comPortList = findSystemAllComPort();
if (comPortList != null && comPortList.size() > 0) {
portName = comPortList.get(0);
}
}
log.debug("开始打开串口:portName=" + portName + ",baudrate=" + b + ",datebits=" + d + ",stopbits=" + s + ",parity=" + p);
//通过端口名称识别指定 COM 端口
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
/**
* open(String TheOwner, int i):打开端口
* TheOwner 自定义一个端口名称,随便自定义即可
* i:打开的端口的超时时间,单位毫秒,超时则抛出异常:PortInUseException if in use.
* 如果此时串口已经被占用,则抛出异常:gnu.io.PortInUseException: Unknown Application
*/
commPort = portIdentifier.open(portName, 5000);
/**
* 判断端口是不是串口
* public abstract class SerialPort extends CommPort
*/
if (commPort instanceof SerialPort) {
serialPort = (SerialPort) commPort;
// 设置串口监听器
this.setListenerToSerialPort(serialPort,this);
/**
* 设置串口参数:setSerialPortParams( int b, int d, int s, int p )
* b:波特率(baudrate)
* d:数据位(datebits),SerialPort 支持 5,6,7,8
* s:停止位(stopbits),SerialPort 支持 1,2,3
* p:校验位 (parity),SerialPort 支持 0,1,2,3,4
* 如果参数设置错误,则抛出异常:gnu.io.UnsupportedCommOperationException: Invalid Parameter
* 此时必须关闭串口,否则下次 portIdentifier.open 时会打不开串口,因为已经被占用
*/
serialPort.setSerialPortParams(b, d, s, p);
log.debug("打开串口 " + portName + " 成功...");
return serialPort;
} else {
log.error("当前端口 " + commPort.getName() + " 不是串口...");
}
} catch (NoSuchPortException e) {
e.printStackTrace();
} catch (PortInUseException e) {
log.warn("串口 " + portName + " 已经被占用,请先解除占用...");
e.printStackTrace();
} catch (UnsupportedCommOperationException e) {
log.warn("串口参数设置错误,关闭串口,数据位[5-8]、停止位[1-3]、验证位[0-4]...");
e.printStackTrace();
if (commPort != null) {//此时必须关闭串口,否则下次 portIdentifier.open 时会打不开串口,因为已经被占用
commPort.close();
}
}catch (TooManyListenersException e){
log.warn("监听对象太多");
e.printStackTrace();
}
log.error("打开串口 " + portName + " 失败...");
return null;
}
@Override
public void serialEvent(SerialPortEvent event) {
System.out.println("串口监听"+event.getEventType());
switch (event.getEventType()) {
/*
* SerialPortEvent.BI:/*Break interrupt,通讯中断
* SerialPortEvent.OE:/*Overrun error,溢位错误
* SerialPortEvent.FE:/*Framing error,传帧错误
* SerialPortEvent.PE:/*Parity error,校验错误
* SerialPortEvent.CD:/*Carrier detect,载波检测
* SerialPortEvent.CTS:/*Clear to send,清除发送
* SerialPortEvent.DSR:/*Data set ready,数据设备就绪
* SerialPortEvent.RI:/*Ring indicator,响铃指示
* SerialPortEvent.OUTPUT_BUFFER_EMPTY:/*Output buffer is empty,输出缓冲区清空
*/
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: break;
// 当有可用数据时读取数据
case SerialPortEvent.DATA_AVAILABLE:
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
byte[] bytes = this.readData(serialPort);
System.out.println(event.getEventType());
if (bytes != null) {
String weight = new String(bytes);
if (StringUtils.isNotBlank(weight)) {
System.out.println("收到的数据长度:" + bytes.length);
System.out.println("重量为:" + weight);
msgQueue.add(weight);
}
}
break;
}
}
}
测试工具
虚拟串口工具 Configure Virtual Serial Port Driver
串口通信工具 友善串口调试助手