在用java读取com串口之前,需要引用一个jar包
RXTXcomm.jar
或者用maven(但是maven我试了,好像不行,下载不下来呢)
<dependency>
<groupId>gnu.io</groupId>
<artifactId>rxtx</artifactId>
<version>2.1.7</version>
</dependency>
还有两个dll文件:rxtxParallel.dll、rxtxSerial.dll
复制 rxtxParallel.dll 和 rxtxSerial.dll 到 C:\Program Files\Java\jdk1.8.0_241\jre\bin 下,
串口工具类
方法:
- openPort打开使用串口
- serialEvent监听串口事件
- getPortTypeName根据端口类型获取端口类型名称
- ComInfo获取所有可用串口
import gnu.io.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Enumeration;
class OpenComUtil implements SerialPortEventListener {
/**
* 打开端口,注意操作顺序,输入流一定要先获取
*/
InputStream inputStream = null;
/**
* 打开指定的通讯端口。
*
* @param comName 需要打开的通讯端口名称。
* @param port 端口。
* @param name 应用程序名,用于标识当前打开端口的应用程序。
* @param baudRate 波特率,即每秒传输的比特数。
* @param dataBits 数据位个数,通常为5、6、7或8。
* @param stopBits 停止位个数,通常为1或2。
* @param parity 校验方式,0代表无奇偶校验,1代表偶校验,2代表奇校验。
*/
void openPort(String comName, int port, String name, int baudRate, int dataBits, int stopBits, int parity) {
try {
/**
* open方法(应用程序名【随意命名】,阻塞时等待的毫秒数)
* open方法打开通讯端口,获得一个CommPort对象,它使程序独占端口。
* 如果端口正被其他应用程序占用,将使用CommPortOwnershipListener事件机制
* 传递一个PORT_OWNERSHIP_REQUESTED事件。
* 每个端口都关联一个InputStream和一个OutputStream,如果端口是用
* open方法打开的,那么任何的getInputStream都将返回相同的数据流对象,除非 有close被调用。
*/
// open:(应用程序名【随意命名】,阻塞时等待的毫秒数)
CommPortIdentifier commPortIdentifier = CommPortIdentifier.getPortIdentifier(comName);
SerialPort serialPort = (SerialPort) commPortIdentifier.open(name, port);
inputStream = serialPort.getInputStream();
// 获取输入流
// 设置串口监听,this对象即本类对象需要继承SerialPortEventListener接口。或者你在这里写一个匿名接口也行。接口内部函数的写法在下面
serialPort.addEventListener(this);
// 设置串口数据时间有效(可监听)
serialPort.notifyOnDataAvailable(true);
serialPort.notifyOnBreakInterrupt(true);
// 设置串口通讯参数,可以参考SerialPort类的源码,里面有相关的常量
// 波特率
// 数据位个数
// 停止位
// 校验方式,0代表无奇偶校验,1代表偶校验,2代表偶校验
serialPort.setSerialPortParams(baudRate, dataBits, stopBits, parity);
} catch (PortInUseException e) {
// 端口正在使用
throw new RuntimeException(e);
} catch (Exception e) {
// 输入输出流错误
throw new RuntimeException(e);
}
}
/**
* 监听:处理串口事件。
*
* @param event 发生的串口事件,包括通讯中断、溢位错误、帧错误、奇偶校验错误、载波检测、清除发送、数据设备准备好、响铃侦测和输出缓冲区已清空等事件。
*/
@Override
public void serialEvent(SerialPortEvent event) {
switch (event.getEventType()) {
/**
* 通讯中断
*/
case SerialPortEvent.BI: {
}
break;
/**
* 溢位错误
*/
case SerialPortEvent.OE: {
}
break;
/**
* 帧错误
*/
case SerialPortEvent.FE: {
}
break;
/**
* 奇偶校验错误
*/
case SerialPortEvent.PE: {
}
break;
/**
* 载波检测
*/
case SerialPortEvent.CD: {
}
break;
/**
* 清除发送
*/
case SerialPortEvent.CTS: {
}
break;
/**
* 数据设备准备好
*/
case SerialPortEvent.DSR: {
}
break;
/**
* 响铃侦测
*/
case SerialPortEvent.RI: {
}
break;
/**
* 输出缓冲区已清空
*/
case SerialPortEvent.OUTPUT_BUFFER_EMPTY: {
}
break;
/**
* 有数据到达
*/
case SerialPortEvent.DATA_AVAILABLE: {
// InputStream 通过serialPort在上面的代码中已经获取到了,在这里通过InputStream 读取字节流即可。字节流的操作和咱们一般用法一致
// 在这里进行读取操作
byte[] bytes = new byte[1024];
try {
int totalBytesRead = 0;
int len = 0;
int cardLength = 10;
while (totalBytesRead < cardLength) { // 你需要读取的字节数
len = inputStream.read(bytes, totalBytesRead, bytes.length - totalBytesRead);
if (len == -1) { // 如果读取到流的末尾,跳出循环
break;
}
totalBytesRead += len;
}
// 检查是否读取到了10位数据
if (totalBytesRead >= cardLength) {
// 截取前10位数据
byte[] cardData = Arrays.copyOfRange(bytes, 0, cardLength);
String data = new String(cardData, 0, cardLength, "UTF-8"); // 假设数据是UTF-8编码
System.out.println("内容:" + data);
// 在这里写 处理data的业务逻辑
} else {
// 处理没有读取到足够数据的情况
System.out.println("未能读取到完整的卡数据");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inputStream.close(); // 关闭流
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
break;
default: {
}
break;
}
}
/**
* 根据端口类型编号获取对应的端口类型名称。
*
* @param portType 端口类型的编号,例如:CommPortIdentifier.PORT_I2C、CommPortIdentifier.PORT_PARALLEL等。
* @return 如果输入的端口类型编号有效,返回对应的端口类型名称;否则返回"unknown type"。
*/
public static String getPortTypeName(int portType) {
switch (portType) {
case CommPortIdentifier.PORT_I2C:
return "I2C";
case CommPortIdentifier.PORT_PARALLEL: // 并口
return "Parallel";
case CommPortIdentifier.PORT_RAW:
return "Raw";
case CommPortIdentifier.PORT_RS485: // RS485端口
return "RS485";
case CommPortIdentifier.PORT_SERIAL: // 串口
return "Serial";
default:
return "unknown type";
}
}
/**
* 获取当前所有可用的串口信息。
* @return 返回一个字符串,包含所有可用串口的名称和类型。每个串口的信息以换行符分隔。
*/
public static String ComInfo() {
String str = "";
// 获取当前所有可用的串口信息
Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();
// 遍历所有的串口信息
while (portList.hasMoreElements()) {
// 获取下一个端口信息
CommPortIdentifier com = (CommPortIdentifier) portList.nextElement();
// 端口的名称
String name = com.getName();
// 端口的类型,需要解析
int portType = com.getPortType();
String typeName = getPortTypeName(portType);
str += "端口名称:" + name + ",端口类型:" + typeName + "\n";
}
return str;
}
}
调用工具类
public class Main {
public static void main(String[] args) {
OpenComUtil open = new OpenComUtil();
open.openPort("COM1",8888,"OpenPortServer",9600,8,1,0);
}
}
标签:case,SerialPortEvent,CommPortIdentifier,java,端口,break,串口,com
From: https://www.cnblogs.com/Gguopeng/p/18489138