java串口通讯
1.Java_第一季_JAVASE_自增、单例模式、类与实例初始化过程、方法参数传递机制、递归和迭代、成员变量与局部变量2.Java_第一季_SSM_Spring Bean的作用域、Spring事务的传播行为、Spring MVC的执行流程、3.Java_第一季_java高级_Redis持久化、MySql何时建立索引4.java_JUC、volatile5.java_CAS6.java_阻塞队列(FIFO先进先出)7.JUC下countDownLatch、CyclicBarrier、Semaphore以及枚举的常见使用方法8.java_锁9.java_集合不安全10.Spring循环依赖11.AbstractQueuedSynchronizer---AQS12.LockSuport13.java_线程池7大参数_底层运行原理14.java_线程池三个常用方式15.Java_Callable<V>的基本使用16.java_锁_synchronized与Lock的区别17.java_强、软、弱、虚四大引用18.java_OOM19.JAVA-interview20.java_NIO21.java_JVM之GC22.java_JVM23.单例模式设计24.netty服务端、客户端简单搭建25.java使用webSocket与前端通讯
26.java串口通讯
27.用Java读取文件文字并语音播报28.Proguard-混淆29.Spring Security30.MQ31.spring相关面试题32.执行jar包33.Spring34.SpringBoot数据访问35.Java Stream(流)基本使用36.java集合工具类 Collections基本使用37.LocalDateTime、LocalDate、Date、String相互转化38.java8新特性39.java设计模式40.java springboot使用定时器41.MQ根据正常队列、死信队列来实现延迟队列的场景1、环境配置
java串口通讯需要依赖两个dll文件 rxtxParallel.dll、rxtxSerial.dll,以及第三方sdk(RXTXcomm.jar);
博客园下载:https://files-cdn.cnblogs.com/files/blogs/666773/rxtx-win-x64.rar
官网下载:http://fizzed.com/oss/rxtx-for-java
两个dll文件需要粘贴到jdk安装目录下 jdk/jre/bin/
当前第三方sdk也可通过pom.xml引入
<dependency> <groupId>org.rxtx</groupId> <artifactId>rxtx</artifactId> <version>2.1.7</version> </dependency>
java:java1.8
<properties> <java.version>1.8</java.version> </properties>
springboot:2.5.6
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
pom.xml如下所示:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.rxtx/rxtx --> <!-- java操作串口需要的jar --> <dependency> <groupId>org.rxtx</groupId> <artifactId>rxtx</artifactId> <version>2.1.7</version> </dependency> <!-- swagger --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency> </dependencies>
SerialPortManager.java
import gnu.io.*; import lombok.extern.slf4j.Slf4j; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Enumeration; import java.util.TooManyListenersException; @Slf4j public class SerialPortManager { //查找所有可用端口 public static ArrayList<String> findPorts() { // 获得当前所有可用串口 Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers(); ArrayList<String> portNameList = new ArrayList<String>(); // 将可用串口名添加到List并返回该List while (portList.hasMoreElements()) { String portName = portList.nextElement().getName(); portNameList.add(portName); } return portNameList; } /** * 打开串口 * * @param portName 端口名称 * @param baudRate 波特率 * @return 串口对象 * @throws PortInUseException 串口已被占用 */ public static SerialPort openPort(String portName, int baudRate) throws PortInUseException { try { // 通过端口名识别端口 CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName); // 打开端口,并给端口名字和一个timeout(打开操作的超时时间) CommPort commPort = portIdentifier.open(portName, 2000); // 判断是不是串口 if (commPort instanceof SerialPort) { SerialPort serialPort = (SerialPort) commPort; try { // 设置一下串口的波特率等参数 // 数据位:8 // 停止位:1 // 校验位:None serialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); } catch (UnsupportedCommOperationException e) { e.printStackTrace(); } return serialPort; } } catch (NoSuchPortException e1) { e1.printStackTrace(); } return null; } /** * 关闭串口 * @param serialPort 待关闭的串口对象 */ public static void closePort(SerialPort serialPort) { if (serialPort != null) { serialPort.close(); } } /** * 往串口发送数据 * @param serialPort 串口对象 * @param content 待发送数据 */ public static void sendToPort(SerialPort serialPort, byte[] content) { OutputStream out = null; try { out = serialPort.getOutputStream(); out.write(content); out.flush(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (out != null) { out.close(); out = null; } } catch (IOException e) { e.printStackTrace(); } } } /** * 从串口读取数据 * @param serialPort 当前已建立连接的SerialPort对象 * @return 读取到的数据 */ public static byte[] readFromPort(SerialPort serialPort) { InputStream in = null; byte[] bytes = {}; try { in = serialPort.getInputStream(); // 缓冲区大小为一个字节 byte[] readBuffer = new byte[1]; int bytesNum = in.read(readBuffer); while (bytesNum > 0) { bytes = AgreementUtil.concat(bytes, readBuffer); bytesNum = in.read(readBuffer); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (in != null) { in.close(); in = null; } } catch (IOException e) { e.printStackTrace(); } } return bytes; } /** * 添加监听器 * @param serialPort 串口对象 * @param listener 串口存在有效数据监听 */ public static void addListener(SerialPort serialPort, DataAvailableListener listener) { try { // 给串口添加监听器 serialPort.addEventListener(new SerialPortListener(listener)); // 设置当有数据到达时唤醒监听接收线程 serialPort.notifyOnDataAvailable(true); // 设置当通信中断时唤醒中断线程 serialPort.notifyOnBreakInterrupt(true); } catch (TooManyListenersException e) { e.printStackTrace(); } } /** * 串口监听 */ public static class SerialPortListener implements SerialPortEventListener { private DataAvailableListener mDataAvailableListener; public SerialPortListener(DataAvailableListener mDataAvailableListener) { this.mDataAvailableListener = mDataAvailableListener; } public void serialEvent(SerialPortEvent serialPortEvent) { switch (serialPortEvent.getEventType()) { case SerialPortEvent.DATA_AVAILABLE: // 1.串口存在有效数据 if (mDataAvailableListener != null) { mDataAvailableListener.dataAvailable(); } break; case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 2.输出缓冲区已清空 break; case SerialPortEvent.CTS: // 3.清除待发送数据 break; case SerialPortEvent.DSR: // 4.待发送数据准备好了 break; case SerialPortEvent.RI: // 5.振铃指示 break; case SerialPortEvent.CD: // 6.载波检测 break; case SerialPortEvent.OE: // 7.溢位(溢出)错误 break; case SerialPortEvent.PE: // 8.奇偶校验错误 break; case SerialPortEvent.FE: // 9.帧错误 break; case SerialPortEvent.BI: // 10.通讯中断 log.error("与串口设备通讯中断"); break; default: break; } } } /** * 串口存在有效数据监听 */ public interface DataAvailableListener { /** * 串口存在有效数据 */ void dataAvailable(); } }
调用示例
/** * @throws PortInUseException 串口已经被占用 */ public static void main(String[] args) throws PortInUseException { //获取可用串口列表 ArrayList<String> ports = SerialPortManager.findPorts(); //当前使用第一个串口,通常串口名称由用户自行控制 String portName = ports.get(0); //波特率,当前使用115200 int baudRate = 115200; //打开串口,返回一个串口对象 SerialPort serialPort = SerialPortManager.openPort(portName, baudRate); //给当前串口对象设置监听器 SerialPortManager.addListener(serialPort, new SerialPortManager.DataAvailableListener() { @Override public void dataAvailable() { //当前监听器监听到的串口返回数据 back byte[] back = SerialPortManager.readFromPort(serialPort); //数据监听完之后,关闭串口 SerialPortManager.closePort(serialPort); } }); //当前向串口发送的数据(模拟假数据) byte[] content = new byte[10]; //向当前串口发送数据 SerialPortManager.sendToPort(serialPort,content); }
参考:https://blog.csdn.net/kong_gu_you_lan/article/details/80589859#commentBox
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?