关于Java读取串口数据
1、准备工作
1.下载RXTX for Java
2.解压文件,Install.txt中有安装方法。我这里使用的Windows所以将rxtxParallel.dll和rxtxSerial.dll复制到jdk安装目录/jdk/jre/bin;将RXTXcomm.jar放入项目的lib中。
2、编码
1.代码整体思路
一个串口数据记录器的Java程序,它可以将从串口接收到的数据记录到文本文件中。程序的界面使用了Swing库来构建,
包括一个下拉框用于选择串口、若干个按钮用于连接、开始记录、停止记录和断开连接、一个用于显示日志的文本区域等。
主要的功能实现在connectToSerialPort()、startLogging()、stopLogging()和closeSerialPort()等方法中,
它们分别对应着连接串口、开始记录、停止记录和关闭串口的操作。
在连接到串口时,程序会弹出文件选择对话框,让用户选择保存数据的文件路径。程序使用了RXTXcomm库来与串口进行交互。
321.上链接
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
public class SerialDataLogger extends JFrame implements ActionListener {
/**
* 串口列表的下拉框
*/
private JComboBox<String> portList;
/**
* 连接按钮
*/
private JButton connectButton;
/**
* 日志显示区域
*/
private JTextArea logArea;
/**
* 开始按钮
*/
private JButton startButton;
/**
* 停止按钮
*/
private JButton stopButton;
/**
* 断开按钮
*/
private JButton closeButton;
/**
* 是否正在记录数据
*/
private boolean isLogging = false;
/**
* 文件写入器
*/
private FileWriter fileWriter;
/**
* 添加文件路径变量
*/
private String filePath;
public SerialDataLogger() {
super("Serial Data Logger");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(800, 400);
setLocationRelativeTo(null);
// 初始化UI组件
JPanel panel = new JPanel(new BorderLayout());
add(panel);
JPanel controlPanel = new JPanel(new FlowLayout());
panel.add(controlPanel, BorderLayout.NORTH);
// 获取可用串口列表
portList = new JComboBox<>(getPortNames());
// 设置JComboBox的大小为宽度200像素,高度30像素
portList.setPreferredSize(new Dimension(80, 30));
controlPanel.add(portList);
connectButton = new JButton("Connect");
connectButton.addActionListener(this);
controlPanel.add(connectButton);
startButton = new JButton("Start");
startButton.addActionListener(this);
startButton.setEnabled(false);
controlPanel.add(startButton);
stopButton = new JButton("Stop");
stopButton.addActionListener(this);
stopButton.setEnabled(false);
controlPanel.add(stopButton);
closeButton = new JButton("Close");
closeButton.addActionListener(this);
closeButton.setEnabled(false);
controlPanel.add(closeButton);
logArea = new JTextArea();
JScrollPane scrollPane = new JScrollPane(logArea);
panel.add(scrollPane, BorderLayout.CENTER);
}
@Override
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (source == connectButton) {
// 连接到选定的串口
connectToSerialPort();
} else if (source == startButton) {
// 开始记录数据
startLogging();
} else if (source == stopButton) {
// 停止记录数据
stopLogging();
} else if (source == closeButton) {
// 关闭串口连接
closeSerialPort();
}
}
InputStream in;
SerialPort serialPort;
private void connectToSerialPort() {
// 获取选定的串口名称
String portName = (String) portList.getSelectedItem();
try {
// 获取选定的串口标识符
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
// 打开选定的串口
serialPort = (SerialPort) portIdentifier.open(getClass().getName(), 2000);
// 设置串口参数
serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
// 获取串口输入流
in = serialPort.getInputStream();
// 在连接时选择文件地址
filePath = getFileName();
if (filePath == null) {
logArea.append("Failed to connect to " + portName + ": Invalid file path\n");
return;
}
// 创建文件写入器
fileWriter = new FileWriter(filePath);
receiveMsg();
connectButton.setEnabled(false);
closeButton.setEnabled(true);
startButton.setEnabled(true);
logArea.append("Connected to " + portName + "\n");
} catch (Exception e) {
logArea.append("Failed to connect to " + portName + ": " + e.getMessage() + "\n");
e.printStackTrace();
}
}
private void receiveMsg() {
// 创建读取数据的线程
Thread readThread = new Thread(() -> {
byte[] buffer = new byte[1024];
int len = -1;
try {
// 从串口读取数据并写入文件
while ((len = in.read(buffer)) > -1 && isLogging) {
String data = new String(buffer, 0, len, StandardCharsets.UTF_8);
// //调试
// if (data != null && !"".equals(data)) {
// System.out.println("=============" + data + "=============");
// }
logArea.append(data);
logArea.setCaretPosition(logArea.getDocument().getLength());
fileWriter.write(data);
fileWriter.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
});
// 启动读取数据的线程
readThread.start();
}
private void startLogging() {
if (!isLogging) {
// 创建文件写入器时不再选择文件地址,直接使用连接时选择的文件地址
if (filePath == null) {
logArea.append("Failed to start logging: Invalid file path\n");
return;
}
try {
// 追加模式打开文件写入器
fileWriter = new FileWriter(filePath, true);
isLogging = true;
startButton.setEnabled(false);
stopButton.setEnabled(true);
logArea.append("Started logging data\n");
receiveMsg();
} catch (IOException e) {
logArea.append("Failed to start logging: " + e.getMessage() + "\n");
e.printStackTrace();
}
}
}
private void stopLogging() {
if (isLogging) {
try {
fileWriter.close(); // 关闭文件写入器
isLogging = false;
startButton.setEnabled(true);
stopButton.setEnabled(false);
logArea.append("Stopped logging data\n");
} catch (IOException e) {
logArea.append("Failed to stop logging: " + e.getMessage() + "\n");
e.printStackTrace();
}
}
}
private void closeSerialPort() {
try {
in.close(); // 关闭输入流
fileWriter.close(); // 关闭文件写入器
serialPort.close(); // 关闭串口对象
// 启用连接按钮 ,停关闭按钮
connectButton.setEnabled(true);
closeButton.setEnabled(false);
startButton.setEnabled(false);
stopButton.setEnabled(false);
logArea.append("Serial port closed\n");
} catch (Exception e) {
logArea.append("Failed to close serial port: " + e.getMessage() + "\n");
e.printStackTrace();
}
}
private String[] getPortNames() {
// 获取可用串口的枚举
Enumeration<CommPortIdentifier> portEnum = CommPortIdentifier.getPortIdentifiers();
java.util.List<String> portList = new java.util.ArrayList<>();
while (portEnum.hasMoreElements()) {
CommPortIdentifier portIdentifier = portEnum.nextElement();
// 只添加串口类型的端口
if (portIdentifier.getPortType() == CommPortIdentifier.PORT_SERIAL) {
portList.add(portIdentifier.getName());
}
}
return portList.toArray(new String[portList.size()]);
}
private String getFileName() {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setDialogTitle("Choose save location");
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
// 弹出文件选择对话框,获取用户选择的保存路径
if (fileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
String fileName = fileChooser.getSelectedFile().toString();
if (!fileName.endsWith(".txt")) {
fileName += ".txt";
}
return fileName;
} else {
return null;
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new SerialDataLogger().setVisible(true));
}
}
3、测试
1.选择串口连接并选择数据输出文件(txt)
2.使用xcom发送数据;打完收工。