目录
一、什么是RS-232?
先看看硬件通讯接口长啥样
RS-232
二、方案一
1.前期准备
a.配置 RXTX
1)下载 RXTX 包并解压
2)拷贝动态库到对应的jdk目录下
·Windows平台
·Linux平台
3)在工程根目录下创建 lib 文件夹(与src平级)将 RXTXcomm.jar 放入该文件夹中
4)在 pom.xml 中引入本地 jar 包依赖
2、编写Java配置代码
三、方案二
1、前期准备
a.配置pom.xml文件
2、编写Java配置代码
四、其他的方法
📢📢📢📣📣📣
哈喽!大家好,我是「Leen」。刚工作几年,想和大家一同进步🤝🤝
一位上进心十足的Java博主!😜😜😜
喜欢尝试一些新鲜的东西,平时比较喜欢研究一些新鲜技术和一些自己没有掌握的技术领域。能用程序解决的坚决不手动解决😜😜😜目前已涉足Java、Python、数据库(MySQL、pgsql、MongoDB、Oracle...)、Linux、HTML、VUE、PHP、C(了解不多,主要是嵌入式编程方向做了一些)...(还在不断地学习,扩展自己的见识和技术领域中),希望可以和各位大佬们一起进步,共同学习🤝🤝
✨ 如果有对【Java】,或者喜欢看一些【实操笔记】感兴趣的【小可爱】,欢迎关注我
❤️❤️❤️感谢各位大可爱小可爱!❤️❤️❤️
今天给大家分享的是Java 连接 RS-232串口进行通讯,研究了好几个日夜,终于是走通了两条通道,实现了通讯,大家自己要实现这个这两个方案前需要硬件支持哦。
OK,接下来直接进入正题
一、什么是RS-232?
先看看硬件通讯接口长啥样
RS-232
RS-232 是电子工业协会 (EIA) 定义的串行通信标准电气接口。RS-232 实际上有 3 种不同的风格(A、B 和 C),每种风格都为开和关电平定义了不同的电压范围。最常用的品种是RS-232C,它将标记(开)位定义为-3V至-12V之间的电压,将空格(关)位定义为+3V至+12V之间的电压。RS-232C 规范规定,这些信号在无法使用之前可以传播约 25 英尺(8 米)。只要波特率足够低,您通常可以发送比这更远的信号。
这一块,大家可以自行搜索去了解一下,这个地方我就不多介绍了
二、方案一
第一个方案,是原始方案,比较老的一种通讯方式,需要给jdk添加相应的ddl配置文件和驱动,并且现在这些配置文件不好找了(因为官网的配置地址找不到了,不存在),当然如果要是花点$,找到的可能性还是比较大的,反正我是没花钱找了一套配置哈哈哈
1.前期准备
a.配置 RXTX
1)下载 RXTX 包并解压
网址:http://fizzed.com/oss/rxtx-for-java
官网我找的时候暂时是没有的,可以等到后面的时候再去看看
2)拷贝动态库到对应的jdk目录下
·Windows平台
拷贝 rxtxSerial.dll —> <JAVA_HOME>\jre\bin
拷贝 rxtxParallel.dll —> <JAVA_HOME>\jre\bin
·Linux平台
拷贝 librxtxSerial.so —> <JAVA_HOME>/jre/lib/i386/
拷贝 librxtxParallel.so —> <JAVA_HOME>/jre/lib/i386/
3)在工程根目录下创建 lib 文件夹(与src平级)将 RXTXcomm.jar 放入该文件夹中
这个地方我建议是通过命令的方式将RXTXcomm.jar包导入到本地的Maven库中
mvn install:install-file -Dfile="绝对路径/RXTXcomm.jar" -DgroupId="org.rxtx" -DartifactId="rxtx" -Dversion="2.2.0" -Dpackaging="jar"
当然也可以选择另外一种方式,直接导入
<dependency>
<groupId>gnu.io</groupId>
<artifactId>RXTXcomm</artifactId>
<scope>system</scope>
<systemPath>${project.basedir}/lib/RXTXcomm.jar</systemPath>
</dependency>
4)在 pom.xml 中引入本地 jar 包依赖
导入成功后,直接添加依赖即可
<dependency>
<groupId>org.rxtx</groupId>
<artifactId>rxtx</artifactId>
<version>2.2.0</version>
</dependency>
2、编写Java配置代码
package com.leen.test.test2024.test530;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
/**
* Author:Leen
* Date: 2024/6/3 0003 22:45
*/
public class SerialCommSendData implements SerialPortEventListener {
private SerialPort serialPort; // 串口对象
private InputStream input; // 输入流,用于读取串口数据
private OutputStream output; // 输出流,用于向串口写入数据
private static final int TIME_OUT = 2000; // 端口打开的超时时间
private static final int DATA_RATE = 9600; // 串口的波特率
// 初始化串口
public void initialize() {
CommPortIdentifier portId = null;
Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();
// 枚举系统中的所有端口并尝试找到指定的端口
while (portEnum.hasMoreElements()) {
CommPortIdentifier currPortId = (CommPortIdentifier) portEnum.nextElement();
if (currPortId.getName().equals("COM3")) { // 将这里的 "COM3" 修改为你的端口名
portId = currPortId;
break;
}
}
if (portId == null) {
System.out.println("Could not find COM port.");
return;
}
try {
// 打开串口,使用类名作为应用程序名
serialPort = (SerialPort) portId.open(this.getClass().getName(), TIME_OUT);
// 设置串口参数
serialPort.setSerialPortParams(DATA_RATE,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
// 打开输入输出流
input = serialPort.getInputStream();
output = serialPort.getOutputStream();
// 添加事件监听器
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
} catch (Exception e) {
System.err.println(e.toString());
}
}
// 关闭串口
public synchronized void close() {
if (serialPort != null) {
serialPort.removeEventListener();
serialPort.close();
}
}
// 事件处理器,当串口有数据可用时触发
@Override
public synchronized void serialEvent(SerialPortEvent oEvent) {
if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
try {
int available = input.available();
byte[] chunk = new byte[available];
input.read(chunk, 0, available);
// 显示结果,具体字符编码依赖于系统设置
System.out.print(new String(chunk));
// processData(chunk); // 处理接收到的数据
} catch (Exception e) {
System.err.println(e.toString());
}
}
}
// 发送数据的方法
public void sendData(String data) {
try {
output.write(data.getBytes());
output.flush();
System.out.println("Data sent: " + data);
} catch (Exception e) {
System.err.println(e.toString());
}
}
// 处理接收到的数据的方法
private void processData(byte[] data) {
// 可以在这里处理接收到的数据
String receivedData = new String(data);
System.out.println("Received: " + receivedData);
}
// 主方法,程序入口
public static void main(String[] args) {
SerialCommSendData main = new SerialCommSendData();
main.initialize(); // 初始化并打开串口
System.out.println("Started");
// 发送数据示例
main.sendData("Hello ,I'm Leen ! I'd like to communicate with you");
//测试接收数据
byte[] data = "TEST communicate with RS-232".getBytes();
main.processData(data);
try {
Thread.sleep(1000000); // 保持程序运行一段时间
} catch (InterruptedException ie) {
// 处理中断异常
}
main.close(); // 关闭串口
}
}
启动main方法后,就可以和硬件串口进行通讯了
这个方法可以通讯,但是需要不适用于团队开发和切环境运行,只适合自己玩一下。咱们可以看看第二个方案
三、方案二
说实话,方案二操作起来非常的简单,唯二的难点之一是需要花时间找依赖;另一点就是正式通讯的时候封装通讯语言
1、前期准备
a.配置pom.xml文件
<dependency>
<groupId>org.scream3r</groupId>
<artifactId>jssc</artifactId>
<version>2.8.0</version>
</dependency>
2、编写Java配置代码
package com.leen.test.test2024.test530;
import jssc.SerialPort;
import jssc.SerialPortException;
import jssc.SerialPortEvent;
import jssc.SerialPortEventListener;
import org.apache.commons.lang3.StringUtils;
/**
* Author:Leen
* Date: 2024/6/4 0004 11:28
*/
public class SerialCommTwo {
private SerialPort serialPort; // 串口对象
private static SerialCommTwo instance; // 单例实例
private StringBuilder receivedDataBuffer = new StringBuilder(); // 缓存接收到的数据
// 私有构造函数
private SerialCommTwo(String portName) {
serialPort = new SerialPort(portName);
}
// 获取单例实例的方法
public static SerialCommTwo getInstance(String portName) {
if (instance == null) {
instance = new SerialCommTwo(portName);
}
return instance;
}
// 初始化串口
public void initialize() {
try {
serialPort.openPort(); // 打开串口
serialPort.setParams(SerialPort.BAUDRATE_9600,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE); // 设置串口参数
serialPort.addEventListener(new SerialPortEventListener() {
public void serialEvent(SerialPortEvent event) {
if (event.isRXCHAR()) { // 如果串口有数据可用
try {
byte[] buffer = serialPort.readBytes(); // 读取数据
// System.out.print(new String(buffer)); // 打印数据
// 缓存接收到的数据
if (StringUtils.isNotEmpty(new String(buffer))) {
receivedDataBuffer.append(new String(buffer));
}
// 在这里处理接收到的完整报文,例如检查结束标志
processReceivedData();
} catch (SerialPortException e) {
e.printStackTrace(); // 捕捉异常
}
}
}
// 处理接收到的数据的方法
private void processReceivedData() {
String receivedData = receivedDataBuffer.toString();
// 检查报文是否完整,例如检查结束标志ETX
if (receivedData.contains("\u0003")) { // ETX结束标志
System.out.println("Received complete message:\n" + receivedData);
// 提取第四行到结束标志中间的内容
String[] lines = receivedData.split("\r\n|\n");
if (lines.length >= 4) {
StringBuilder extractedData = new StringBuilder();
for (int i = 3; i < lines.length; i++) {
if (lines[i].contains("\u0003")) { // 如果包含结束标志,停止提取
break;
}
extractedData.append(lines[i]).append("\n");
}
System.out.println("Extracted data: \n" + extractedData.toString());
}
// 处理完成的报文后,清空缓存
receivedDataBuffer.setLength(0);
}
}
});
} catch (SerialPortException e) {
e.printStackTrace(); // 捕捉异常
}
}
// 发送数据的方法
public void sendData(String data) {
try {
serialPort.writeBytes(data.getBytes()); // 发送数据
System.out.println("Sent: " + data); // 打印已发送的数据
} catch (SerialPortException e) {
e.printStackTrace(); // 捕捉异常
}
}
// 关闭串口
public void close() {
try {
if (serialPort != null) {
serialPort.removeEventListener(); // 移除事件监听器
serialPort.closePort(); // 关闭串口
}
} catch (SerialPortException e) {
e.printStackTrace(); // 捕捉异常
}
}
public static void main(String[] args) {
SerialCommTwo serialComm = SerialCommTwo.getInstance("COM3"); // 替换为你的串口名
serialComm.initialize(); // 初始化串口
System.out.println("Started");
// 发送测试数据
String startChar = "\u0001"; // SOH 开始字符
String endChar = "\u0003"; // ETX 结束字符
serialComm.sendData(startChar +
"Hello ,I'm Leen ! I'd like to communicate with you \n" +
endChar);
try {
Thread.sleep(1000000); // 保持程序运行一段时间以接收数据
} catch (InterruptedException ie) {
ie.printStackTrace(); // 捕捉异常
}
serialComm.close(); // 关闭串口
}
}
启动main方法后,就可以和硬件串口进行通讯了
四、其他的方法
这个方法在这里不适用,可能对于别的地方有适用的
package com.leen.test.test2024.test530;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
/**
* Author:Leen
* Date: 2024/5/30 0030 21:01
*/
public class NPortClient {
private static final String SERVER_IP = "192.168.1.100"; // NPort的IP地址
private static final int SERVER_PORT = 4001; // NPort的端口号
public static void main(String[] args) {
try (Socket socket = new Socket(SERVER_IP, SERVER_PORT);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
System.out.println("Connected to NPort at " + SERVER_IP + ":" + SERVER_PORT);
// 发送数据到NPort(可选)
out.println("Hello NPort!");
// 接收来自NPort的数据
String response;
while ((response = in.readLine()) != null) {
System.out.println("Received from NPort: " + response);
// 可以在这里处理接收到的数据
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
package com.leen.test.test2024.test530;
import java.io.*;
import java.net.Socket;
import java.net.SocketException;
import java.util.Properties;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Author:Leen
* Date: 2024/5/30 0030 21:05
*/
public class NPortClient2 {
/**
* 可放配置文件
* server.ip=192.168.1.100
* server.port=4001
* reconnect.delay=5000 # 重连间隔时间(毫秒)
*/
private static final Logger LOGGER = Logger.getLogger(NPortClient.class.getName());
private static String serverIp;
private static int serverPort;
private static int reconnectDelay;
private static boolean running = true;
public static void main(String[] args) {
loadConfig();
ExecutorService executor = Executors.newFixedThreadPool(2);
while (running) {
try (Socket socket = new Socket(serverIp, serverPort);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
LOGGER.info("Connected to NPort at " + serverIp + ":" + serverPort);
// 启动接收数据线程
executor.submit(() -> receiveData(in));
// 发送数据示例(可根据需要调整)
out.println("Hello NPort!");
} catch (Exception e) {
LOGGER.log(Level.WARNING, "Connection failed, retrying in " + reconnectDelay + "ms", e);
try {
Thread.sleep(reconnectDelay);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
}
executor.shutdown();
}
private static void receiveData(BufferedReader in) {
String response;
try {
while ((response = in.readLine()) != null) {
LOGGER.info("Received from NPort: " + response);
// 根据需要解析数据
}
} catch (SocketException e) {
LOGGER.warning("Connection reset by peer, attempting to reconnect.");
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "I/O error occurred", e);
}
}
private static void loadConfig() {
try (InputStream input = NPortClient.class.getClassLoader().getResourceAsStream("config.properties")) {
Properties prop = new Properties();
if (input == null) {
LOGGER.severe("Sorry, unable to find config.properties");
return;
}
prop.load(input);
serverIp = prop.getProperty("server.ip");
serverPort = Integer.parseInt(prop.getProperty("server.port"));
reconnectDelay = Integer.parseInt(prop.getProperty("reconnect.delay"));
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, "Error loading configuration", ex);
}
}
}
欢迎大家在评论区讨论,今天的干货分享就到此结束了,如果觉得对您有帮助,麻烦给个三连!
以上内容为本人的经验总结和平时操作的笔记。若有错误和重复请联系作者删除!!感谢支持!!