一、环境搭建
本文的串口通信开发基于RXTX,所以需要引用RXTX的依赖包。
下载地址:RXTX的依赖包(32位、64位)
下载完成之后,
拷贝 rxtxSerial.dll 、 rxtxParallel.dll 两个文件到 jdk安装目录\jre\bin目录中;
将RXTXcomm.jar包复制到eclipse工程文件里,
右键单击这个jar包,
选中【Build Path】,
然后点击【Add to Build Path】即可。
(用其他软件的步骤可能略有不同)
二、串口基本信息类 ParamConfig
public class ParamConfig {
private String serialNumber; // 串口号
private int baudRate; // 波特率
private int checkoutBit; // 校验位
private int dataBit; // 数据位
private int stopBit; // 停止位
public ParamConfig() {} //无参构造函数
/**
* 构造方法
* @param serialNumber 串口号
* @param baudRate 波特率
* @param checkoutBit 校验位
* @param dataBit 数据位
* @param stopBit 停止位
*/
public ParamConfig(String serialNumber, int baudRate, int checkoutBit, int dataBit, int stopBit) {
this.serialNumber = serialNumber;
this.baudRate = baudRate;
this.checkoutBit = checkoutBit;
this.dataBit = dataBit;
this.stopBit = stopBit;
}
public String getSerialNumber() {
return serialNumber;
}
public void setSerialNumber(String serialNumber) {
this.serialNumber = serialNumber;
}
public int getBaudRate() {
return baudRate;
}
public void setBaudRate(int baudRate) {
this.baudRate = baudRate;
}
public int getCheckoutBit() {
return checkoutBit;
}
public void setCheckoutBit(int checkoutBit) {
this.checkoutBit = checkoutBit;
}
public int getDataBit() {
return dataBit;
}
public void setDataBit(int dataBit) {
this.dataBit = dataBit;
}
public int getStopBit() {
return stopBit;
}
public void setStopBit(int stopBit) {
this.stopBit = stopBit;
}
}
三、串口工具类 SerialPortUtils
- 初始化串口方法 init( ParamConfig paramConfig )
- 将数据写入串口 sendToPort( String order ) 方法
- 从串口读取数据 readFromPort( ) 方法
- 对串口进行监听
- 其他
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.TooManyListenersException;
import gnu.io.CommPortIdentifier;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import gnu.io.UnsupportedCommOperationException;
public class SerialPortUtils implements SerialPortEventListener{
// 检测系统中可用的通讯端口类
private CommPortIdentifier commPortId;
// 枚举类型
private Enumeration<CommPortIdentifier> portList;
// RS232串口
private SerialPort serialPort;
// 输入流
private InputStream inputStream;
// 输出流
private OutputStream outputStream;
//数据输出流
private DataOutputStream dos;
// 保存串口返回信息
private String data;
// 保存串口返回信息十六进制
private String dataHex;
/**
* 初始化串口
* @author YangJiaxuan&HuangJinshan
* @date 2021年6月23日
* @Description: TODO
* @param: paramConfig 存放串口连接必要参数的对象(会在下方给出类代码)
* @return: void
* @throws
*/
@SuppressWarnings("unchecked")
public void init(ParamConfig paramConfig) {
// 获取系统中所有的通讯端口
portList = CommPortIdentifier.getPortIdentifiers();
// 记录是否含有指定串口
boolean isExsist = false;
// 循环通讯端口
while (portList.hasMoreElements()) {
commPortId = portList.nextElement();
// 判断是否是串口
if (commPortId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
// 比较串口名称是否是指定串口
if (paramConfig.getSerialNumber().equals(commPortId.getName())) {
// 串口存在
isExsist = true;
// 打开串口
try {
// open:(应用程序名【随意命名】,阻塞时等待的毫秒数)
serialPort = (SerialPort) commPortId.open(Object.class.getSimpleName(), 2000);
// 设置串口监听
serialPort.addEventListener(this);
// 设置串口数据时间有效(可监听)
serialPort.notifyOnDataAvailable(true);
// 设置串口通讯参数:波特率,数据位,停止位,校验方式
serialPort.setSerialPortParams(paramConfig.getBaudRate(), paramConfig.getDataBit(),
paramConfig.getStopBit(), paramConfig.getCheckoutBit());
} catch (PortInUseException e) {
System.out.println("端口被占用");
} catch (TooManyListenersException e) {
System.out.println("监听器过多");
} catch (UnsupportedCommOperationException e) {
System.out.println("不支持的COMM端口操作异常");
}
// 结束循环
break;
}
}
}
// 若不存在该串口则抛出异常
if (!isExsist) {
System.out.println("不存在该串口!");
}
}
/**
* 实现接口SerialPortEventListener中的方法 读取从串口中接收的数据
*/
@Override
public void serialEvent(SerialPortEvent event) {
switch (event.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: // 输出缓冲区已清空
break;
case SerialPortEvent.DATA_AVAILABLE: // 有数据到达
// 调用读取数据的方法
readFromPort();
break;
default:
break;
}
}
/**
* 读取串口返回信息
* @author YangJiaxuan
* @date 2021年6月23日下午3:43:04
* @return: void
*/
public void readFromPort() {
try {
inputStream = serialPort.getInputStream();
DataInputStream dis = new DataInputStream(inputStream);
String data=dis.readUTF();
System.out.println(data);
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendToPort(String order) {
OutputStream out = null;
try {
outputStream = serialPort.getOutputStream();
dos = new DataOutputStream(outputStream);
dos.writeUTF(order);
dos.flush();
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 关闭串口
* @author YangJiaxuan
* @date 2021年6月23日下午3:43:04
* @Description: 关闭串口
* @param:
* @return: void
* @throws
*/
public void closeSerialPort() {
if (serialPort != null) {
serialPort.notifyOnDataAvailable(false);
serialPort.removeEventListener();
if (inputStream != null) {
try {
inputStream.close();
inputStream = null;
} catch (IOException e) {
System.out.println("关闭输入流时发生IO异常");
e.printStackTrace();
}
}
if (outputStream != null) {
try {
outputStream.close();
outputStream = null;
} catch (IOException e) {
// throw new CustomException("关闭输出流时发生IO异常");
}
}
serialPort.close();
serialPort = null;
}
}
}
四、测试类 Test
大家可以在此基础上增加新的功能,例如图形化界面。
public class Test{
public static void main(String[] args) {
// 实例化串口操作类对象
SerialPortUtils serialPort = new SerialPortUtils();
// 创建串口必要参数接收类并赋值,赋值串口号,波特率,校验位,数据位,停止位
ParamConfig paramConfig = new ParamConfig("COM1", 38400, 0, 8, 1);
// 初始化设置,打开串口,开始监听读取串口数据
serialPort.init(paramConfig);
// 调用串口操作类的sendComm方法发送数据到串口
serialPort.sendToPort("写入串口的信息,支持中文");
// 关闭串口
serialPort.closeSerialPort();
}
}
五、完整实例
以图像界面的方式,类似于聊天软件
下图完整实例,点击此处下载