Java 串口通信全攻略:技术详解与应用实例
Java串口通信介绍
概述:用Java的方式和我们的硬件(传感器)通过串口(COM3)实现数据交互等功能,基于UART协议实现
串口(串行端口)通信
Java串口通讯是指使用Java编程语言与串行端口(串口)进行数据通讯的过程,通过数据信号线 、地线、控制线等,按位进行传输数据的一种通讯方式(注意,是一位一位的传输,区别于并口通讯,传输慢)。这种通信方式使用的数据线少,在远距离通信中可以节约通信成本,但其传输速度比并行传输低。虽然说慢,不如并,但不代表就要抛弃,某些项目还是很有用的,例如公司最近营养探索馆的一个血压探测仪,就是串口通讯,需要开发串口。
优点:
- 适用性广泛: 串口通讯通常用于连接各种外部设备,如传感器、控制器、调制解调器等,因此适用性非常广泛。
- 线缆简单: 串口通讯只需要少量的线缆就能实现数据传输,因此在布线和连接方面比较简单。
- 长距离传输: 串口通讯可以通过串口转以太网等设备实现远程通讯,支持长距离传输。
缺点:
- 速度相对较慢: 串口通讯的传输速度通常比较慢,受到硬件限制,无法满足高速数据传输的需求。
- 连接设备数量有限: 串口通讯通常只支持连接少量外部设备,无法承载大规模设备连接的需求。
并口通信
并口通讯是通过计算机的并行接口(并口)进行数据传输的方式。并口通讯可以同时传输多个比特(通常是8位或更多),因此传输速度相对较快。并口通讯通常用于连接一些需要高速数据传输的外部设备,如打印机、扫描仪等。并口通讯所需的线缆较为复杂,包括大量的数据线和控制线,连接和布线相对复杂。
优点:
- 高速传输: 并口通讯支持并行传输,因此传输速度相对较快,在某些应用场景下能够满足高速数据传输的需求。
- 多设备连接: 并口通讯通常支持连接多个外部设备,能够满足一定规模的设备连接需求。
缺点:
- 线缆复杂: 并口通讯所需的线缆较为复杂,包括大量的数据线和控制线,因此在布线和连接方面相对复杂。
- 不易远程传输: 由于线缆复杂和传输方式的限制,通常不能实现远程数据传输。
综合来看,串口通讯适用性广泛、连接简单,但传输速度较慢;而并口通讯传输速度快,能够连接多个设备,但线缆复杂且不易远程传输。因此在实际应用中,选择串口通讯还是并口通讯取决于具体的应用场景和需求。
实现方式
1.通过comm.jar实现太老了,对jdk版本有要求(jdk 1.8 32bit),也要配置dll文件
2.通过RXTXcomm.jar实现(更新慢),需要配置dll文件,打包可能会出错
3.通过jserialcomm实现(推荐)跨平台,兼容性好
1.通过comm.jar实现
准备工作
1.下载comm.jar相关资源,将javax.comm.properties,win32com.dll配置文件放到jdk的bin和lib目录
2.准备好一个串口工具,和模拟串口的工具,便于测试
关于依赖引用问题:
当maven拉取不到相关依赖时,有两种解决方案
1.作为资源文件夹内的资源引用
我们可以选择将该依赖的jar包下载下来,通过创建lib文件夹的方式将依赖添加到项目中
<dependency>
<groupId>gun.io</groupId>
<artifactId>rxtx</artifactId>
<version>1.0.0</version>
<!--system,类似provided,需要显式提供依赖的jar以后,Maven就不会在Repository中查找它-->
<scope>system</scope>
<systemPath>${project.basedir}/lib/RXTXcomm.jar</systemPath>
</dependency>
2.将jar包手动安装到maven仓库
实现步骤
1.用Configure Virtual Serial Port Driver虚拟串口工具模拟2个串口号
2.导入相应依赖 comm.jar包并添加到项目中,jdk版本为1.8 32bit
3.通过comm.jar包提供的方法和串口建立通讯
4.通过CommPortIdentifier.getPortIdentifiers()方法获取可用串口
5.选择合适端口,通过该commPort.open()方法打开该端口
6.设置常用参数,如波特率,停止位,校验位等 serialPort.setSerialPortParams()
7.端口打开后,可用通过serialPort.addEventListener()方法添加监听器监听我们之前打开的端口
8.通过程序向端口发送数据,核心是基于流的形式,通过outputStream.write()发送数据
相关代码
package com.xxxx.ckcomm.utils;
import javax.comm.*;
import java.io.*;
import java.util.*;
public class DSerialPort implements Runnable, SerialPortEventListener {
private String appName = "串口通讯测试";
private int timeout = 2000;// open 端口时的等待时间,延迟时间(毫秒数)
private int threadTime = 0;
private CommPortIdentifier commPort;
private SerialPort serialPort;
private InputStream inputStream;
private OutputStream outputStream;
//当前接收COM口的数据
public static String receiptDataString = "";
//当前已取的数组下标
public static int nowDataIndex = 0;
//当前接收COM口的数据自动切割成StringList
public static ArrayList<String> receiptDataList = new ArrayList<String>();
static {
String driverName = "com.sun.comm.Win32Driver";
CommDriver driver;
try {
driver = (CommDriver) Class.forName(driverName).newInstance();
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
driver.initialize();
}
/**
* @方法名称 :listPort
* @功能描述 :列出所有可用的串口
* @返回值类型 :List<String>
*/
@SuppressWarnings("rawtypes")
public List<String> listPort() {
//获得当前所有可用串口
Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();
ArrayList<String> portNameList = new ArrayList<>();
//将可用串口名添加到List并返回该List
while (portList.hasMoreElements()) {
String portName = portList.nextElement().getName();
portNameList.add(portName);
}
return portNameList;
}
/**
* @param portName
* @方法名称 :selectPort
* @功能描述 :选择一个端口,比如:COM1
* @返回值类型 :void
*/
@SuppressWarnings("rawtypes")
public void selectPort(String portName) {
this.commPort = null;
CommPortIdentifier cpid;
Enumeration portList = CommPortIdentifier.getPortIdentifiers();
while (portList.hasMoreElements()) {
System.out.println("串口接口调用成功");
cpid = (CommPortIdentifier) portList.nextElement();
if (cpid.getPortType() == CommPortIdentifier.PORT_SERIAL && cpid.getName().equals(portName)) {
this.commPort = cpid;
break;
}
}
openPort();
}
/**
* @方法名称 :openPort
* @功能描述 :打开SerialPort
* @返回值类型 :void
*/
private void openPort() {
if (commPort == null)
log("无法找到串口!");
else {
log("端口选择成功,当前端口:" + commPort.getName() + ",现在实例化 SerialPort:");
try {
serialPort = (SerialPort) commPort.open(appName, timeout);//打开端口
serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
//设置参数
log("实例 SerialPort 成功!");
} catch (PortInUseException e) {
throw new RuntimeException(String.format("端口'%1$s'正在使用中!", commPort.getName()));
} catch (UnsupportedCommOperationException e) {
e.printStackTrace();
}
}
}
/**
* @方法名称 :checkPort
* @功能描述 :检查端口是否正确连接
* @返回值类型 :void
*/
public void checkPort() {
if (commPort == null)
throw new RuntimeException("没有选择端口,请使用 " + "selectPort(String portName) 方法选择端口");
if (serialPort == null) {
throw new RuntimeException("SerialPort 对象无效!");
}
}
/**
* @方法名称 :write
* @功能描述 :向端口发送数据,请在调用此方法前 先选择端口,并确定SerialPort正常打开!
* @返回值类型 :void
*/
public void write(String message) {
checkPort();
try {
outputStream = new BufferedOutputStream(serialPort.getOutputStream());
} catch (IOException e) {
throw new RuntimeException("获取端口的OutputStream出错:" + e.getMessage());
}
try {
outputStream.write(message.getBytes());
log("信息发送成功!");
} catch (IOException e) {
throw new RuntimeException("向端口发送信息时出错:" + e.getMessage());
} finally {
try {
outputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
public void write(byte[] message) {
checkPort();
try {
outputStream = new BufferedOutputStream(serialPort.getOutputStream());
} catch (IOException e) {
throw new RuntimeException("获取端口的OutputStream出错:" + e.getMessage());
}
try {
outputStream.write(message);
log("信息发送成功!");
} catch (IOException e) {
throw new RuntimeException("向端口发送信息时出错:" + e.getMessage());
} finally {
try {
outputStream.close();
} catch (Exception e) {
}
}
}
/**
* @param time 监听程序的存活时间,单位为秒,0 则是一直监听
* @方法名称 :startRead
* @功能描述 :开始监听从端口中接收的数据
* @返回值类型 :void
*/
public void startRead(int time) {
checkPort();
try {
inputStream = new BufferedInputStream(serialPort.getInputStream());
} catch (IOException e) {
throw new RuntimeException("获取端口的InputStream出错:" + e.getMessage());
}
try {
serialPort.addEventListener(this);//向SerialPort对象中添加串口事件监听器
} catch (TooManyListenersException e) {
throw new RuntimeException(e.getMessage());
}
serialPort.notifyOnDataAvailable(true);//设置串口有数据的事件true有效,false无效
log(String.format("开始监听来自'%1$s'的数据--------------", commPort.getName()));
if (time > 0) {
this.threadTime = time * 1000;
Thread t = new Thread(this);
t.start();
log(String.format("监听程序将在%1$d秒后关闭。。。。", threadTime));
}
}
/**
* @方法名称 :close
* @功能描述 :关闭 SerialPort
* @返回值类型 :void
*/
public void close() {
serialPort.close();
serialPort = null;
commPort = null;
}
public void log(String msg) {
System.out.println(appName + " --> " + msg);
}
/**
* 数据接收的监听处理函数
*/
@Override
public void serialEvent(SerialPortEvent arg0) {
switch (arg0.getEventType()) {
case SerialPortEvent.BI:/* Break interrupt,通讯中断 */
case SerialPortEvent.OE:/* Overrun error,溢位错误 */
case SerialPortEvent.FE:/* Framing error,传帧错误 */
case SerialPortEvent.PE:/* Parity error,校验错误 */
case SerialPortEvent.CD:/* Carrier detect,载波检测 */
case SerialPortEvent.CTS:/* Clear to send,清除发送 */
case SerialPortEvent.DSR:/* Data set ready,数据设备就绪 */
case SerialPortEvent.RI:/* Ring indicator,响铃指示 */
case SerialPortEvent.OUTPUT_BUFFER_EMPTY:/*
* Output buffer is
* empty,输出缓冲区清空
*/
break;
case SerialPortEvent.DATA_AVAILABLE:/*
* Data available at the serial
* port,端口有可用数据。读到缓冲数组,输出到终端
*/
byte[] readBuffer = new byte[1024];
StringBuilder readStr = new StringBuilder();
String s2 = "";
try {
while (inputStream.available() > 0) {
inputStream.read(readBuffer);
readStr.append(new String(readBuffer).trim());
}
s2 = new String(readBuffer).trim();
//接收的精华再这里
//1。readStr为当次读入的,一般设备是1位1位读,模拟的时候就很多位,但是不重要
//2。receiptDataString是用来缓存输入字符串的
//3。receiptDataString.length()==XX这里可以设定你要接受的长度,然后接收指定数据
//4。超长或者不符合长度,你可以看情况抛弃数据或者清空,或者累加
//5。接受成功的数据,放入receiptDataList供获取调用
//6。nowDataIndex是当前数组的下标,可以参考PortController中对数据获取的方法
log("接收端口COM->返回数据(长度为" + readStr.length() + "):数据" + s2);
receiptDataString += readStr;
log("receiptDataString->长度" + receiptDataString.length() + "),数据" + receiptDataString);
if (receiptDataString.length() == 58) {
receiptDataList.add(receiptDataString);
receiptDataString = "";
log("校验通过,数据接收成功");
} else if (receiptDataString.length() > 100) {
receiptDataString = "";
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
@Override
public void run() {
try {
timerTest(threadTime);
serialPort.close();
} catch (Exception e) {
e.printStackTrace();
}
}
//监听串口指定时间,以秒为单位
public void timerTest(int minutes){
Timer timer = new Timer();
timer.schedule(new TimerTask() {
int secondsLeft = minutes ;
public void run() {
if (secondsLeft > 0) {
secondsLeft--;
} else {
log(String.format("端口'%1$s'监听关闭了!", commPort.getName()));
timer.cancel(); // 结束计时器
}
}
}, 0, 1000); // 每隔一秒执行一次
}
public static void main(String[] args) {
DSerialPort sp = new DSerialPort();
sp.listPort();
sp.selectPort("COM3");
sp.write("2");
sp.startRead(120);
sp.close();
}
}
2.通过RXTXcomm.jar实现
准备工作
1.下载RXTXcomm的资源包
2.将rxtxParallel.dll和rxtxSerial.dll两个文件放到jdk下jre的bin目录
实现步骤
1.导入RXTXcomm.jar的依赖
2.建立连接,通过CommPortIdentifier.getPortIdentifier(portName)方法可用获取到对应端口的对象
3.打开端口,portIdentifier.open(portName, timeout);/portName:端口名 timeout:超时时间
4.判断该端口是否为串口,如果是设置串口的参数,如波特率,停止位,数据位,检验位
serialPort.setSerialPortParams(baudRate, SerialPort.*DATABITS_8*, SerialPort.*STOPBITS_1*,SerialPort.*PARITY_NONE*);
5.添加监听器,监听我们打开的端口,用于获取传感器向我们发送的数据
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);//设置串口数据时间有效(可监听)
6.关闭串口,serialPort.close();
相关代码
SeriaTool.class
package com.xxxx.rxtxcomm.utils;
import com.alibaba.fastjson.JSON;
import com.xxxx.rxtxcomm.entity.SmCommMsg;
import com.xxxx.rxtxcomm.exception.BusinessException;
import com.xxxx.rxtxcomm.mqtt.MqttUtil;
import com.xxxx.rxtxcomm.response.ResultCode;
import com.xxxx.rxtxcomm.service.CommService;
import gnu.io.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* @author Long
*/
public class SerialTool implements SerialPortEventListener {
private static SerialPort serialPort;
private static InputStream input;
private static OutputStream output;
private static volatile SerialTool serialTool;
/**
* 获取提供服务的SerialTool对象
*
* @return serialTool
*/
public static SerialTool getInstance() {
if (serialTool == null) {
synchronized (SerialTool.class) { //使用同步锁进行双重确认,防止生成两个实例
if (serialTool == null) {
serialTool = new SerialTool();
}
}
}
return serialTool;
}
//私有化SerialTool类的构造方法,不允许其他类生成SerialTool对象
private SerialTool() {
}
/**
* 查找所有可用串口
*
* @return 可用端口名称列表
*/
public List<String> findPort() {
//获取系统中所有通讯端口
Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();
List<String> portNameList = new ArrayList<>();
//将可用串口名添加到List并返回该List
while (portList.hasMoreElements()) {
CommPortIdentifier commPortIdentifier = portList.nextElement();
//判断是否是串行端口
if (commPortIdentifier.getPortType() == CommPortIdentifier.PORT_SERIAL) {
String portName = commPortIdentifier.getName();
portNameList.add(portName);
}
}
return portNameList;
}
/**
* 打开串口
*
* @param portName 端口名称
* @param baudRate 波特率
*/
public void openPort(String portName, int baudRate) {
try {
//通过端口名识别端口
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
//打开端口,并给端口名字和一个timeout(打开操作的超时时间)
CommPort commPort = portIdentifier.open(portName, 2000);
//判断是不是串口
if (commPort instanceof SerialPort) {
serialPort = (SerialPort) commPort;
try {
//设置一下串口的波特率等参数
serialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
input = serialPort.getInputStream();
output = serialPort.getOutputStream();
serialPort.addEventListener(this);
//设置当有数据到达时唤醒监听接收线程
serialPort.notifyOnDataAvailable(true);
//设置当通信中断时唤醒中断线程
serialPort.notifyOnBreakInterrupt(true);
} catch (UnsupportedCommOperationException e) {
throw new BusinessException(ResultCode.PARAM_NOT_COMPLETE.getCode(), ResultCode.PARAM_NOT_VALID.getMessage());
} catch (IOException e) {
throw new RuntimeException(e);
} catch (TooManyListenersException e) {
throw new BusinessException(ResultCode.COMM_PORT_LISTENERS_MANY.getCode(), ResultCode.COMM_PORT_LISTENERS_MANY.getMessage());
}
System.out.println("Open " + portName + " successfully !");
System.out.println("-- 开始监听 " + portName + " 端口的数据 --");
} else {
throw new BusinessException(ResultCode.COMM_PORT_NOT_PORT.getCode(), ResultCode.COMM_PORT_NOT_PORT.getMessage());
}
} catch (Exception e1) {
try {
throw new Exception();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
/**
* 关闭串口
*/
public void closePort() {
if (serialPort != null) {
serialPort.close();
}
if (input != null) {
try {
input.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if (output != null) {
try {
output.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
/**
* 往串口发送数据
*
* @param order 待发送数据
*/
public void sendToPort(String message) {
try {
output = serialPort.getOutputStream();
output.write(message);
output.flush();
System.out.println("成功发送数据,发送的数据为:" + message);
System.out.println("========================================================================");
System.out.println();
} catch (IOException e) {
try {
throw new Exception();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
@Override
public synchronized void serialEvent(SerialPortEvent oEvent) {
try {
//让该线程延迟一会,保证输出的顺序性,先发数据,在接收数据
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
switch (oEvent.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: // 有数据到达
// 调用读取数据的方法
readData();
break;
default:
break;
}
}
public void readData() {
try {
String strMsg = "";
int len = input.available();
byte[] buffer = new byte[len];
input.read(buffer, 0, len);
String data = DataChangeUtil.byteArrayToHexString(buffer);
// 处理接收到的数据
System.out.println("接收到的数据为==> " + data);
System.out.println("========================================================================");
System.out.println();
} catch (Exception e) {
e.printStackTrace();
}
}
}
package com.xxxx.rxtxcomm.controller;
import com.xxxx.rxtxcomm.response.R;
import com.xxxx.rxtxcomm.service.CommService;
import com.xxxx.rxtxcomm.utils.SerialTool;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@Api(value = "Java串口通讯测试")
public class CommController {
public static SerialTool serialTool = SerialTool.getInstance();
@ApiOperation(value = "初始化串口")
@PostMapping("/init")
public R init(String portName, int baudRate) {
serialTool.openPort(portName, baudRate);
return R.ok();
}
@ApiOperation(value = "向传感器发送消息")
@PostMapping("/sendMsg")
public R sendMsg(String message) {
serialTool.sendToPort(message);
return R.ok();
}
@ApiOperation(value = "释放资源,关闭串口")
@PostMapping("/closePort")
public R closePort() {
serialTool.closePort();
return R.ok();
}
}
3.通过jserialcomm实现
实现步骤
1.引入依赖
<dependency>
<groupId>com.fazecast</groupId>
<artifactId>jSerialComm</artifactId>
<version>[2.0.0,3.0.0)</version>
</dependency>
2.和模块建立连接
SerialPort serialPort=SerialPort.getCommPort(portName) //portName:端口名 例如:COM3
3.通过SerialPort的实例化对象添加一个监听器
serialPort.addDataListener(new DataListener());(DataListenner为自定义类)
4.开始向模块发送指令,如读取传感器监测气体类型
serialPort.writeBytes(data, data.length);
5.如果传感器有回传数据,此时我们的监听器会监听并记录
@Override
public void serialEvent(SerialPortEvent event) {
if (event.getEventType() != SerialPort.LISTENING_EVENT_DATA_AVAILABLE) return;
SerialPort comPort = event.getSerialPort();
byte[] newData = new byte[comPort.bytesAvailable()];
comPort.readBytes(newData, newData.length);
readData(newData);
}
6.释放资源,关闭端口
serialPort.closePort();
相关代码
package com.xxxx.jserialcomm.utils;
import com.fazecast.jSerialComm.SerialPort;
import com.fazecast.jSerialComm.SerialPortDataListener;
import com.fazecast.jSerialComm.SerialPortEvent;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class SerialCommUtil {
private SerialPort serialPort;
private static SerialCommUtil serialCommUtil;
public static SerialCommUtil getSerialCommUtil() {
if (serialCommUtil == null) {
synchronized (SerialCommUtil.class) {
if (serialCommUtil == null) {
serialCommUtil = new SerialCommUtil();
}
}
}
return serialCommUtil;
}
/**
* 打开串口
*
* @param portName 串口名称(例如 "COM3" 或 "/dev/ttyUSB0")
* @param baudRate 波特率
* @return 是否成功打开
*/
public boolean openPort(String portName, int baudRate) {
serialPort = SerialPort.getCommPort(portName);
serialPort.setBaudRate(baudRate);
serialPort.setNumDataBits(8);
serialPort.setNumStopBits(SerialPort.ONE_STOP_BIT);
serialPort.setParity(SerialPort.NO_PARITY);
boolean flag = serialPort.openPort();
serialPort.addDataListener(new DataListener());
return flag;
}
/**
* 关闭串口
*/
public void closePort() {
if (serialPort != null && serialPort.isOpen()) {
serialPort.closePort();
}
}
/**
* 发送数据
*
* @param data 要发送的数据
* @return 是否成功发送
*/
public boolean sendData(byte[] data) {
if (serialPort == null || !serialPort.isOpen()) {
return false;
}
int bytesSent = serialPort.writeBytes(data, data.length);
return bytesSent == data.length;
}
// 数据监听器
private static class DataListener implements SerialPortDataListener {
@Override
public int getListeningEvents() {
return SerialPort.LISTENING_EVENT_DATA_AVAILABLE;
}
@Override
public void serialEvent(SerialPortEvent event) {
if (event.getEventType() != SerialPort.LISTENING_EVENT_DATA_AVAILABLE) return;
SerialPort comPort = event.getSerialPort();
byte[] newData = new byte[comPort.bytesAvailable()];
comPort.readBytes(newData, newData.length);
readData(newData);
}
}
public static void readData(byte[] newData) {
try {
String data = DataChangeUtil.byteArrayToHexString(newData);
// 处理接收到的数据
System.out.println("接收到的数据为: " + data);
System.out.println("========================================================================");
System.out.println();
} catch (Exception e) {
log.error("Bad Things",e);
}
}
/**
* 接收数据
*
* @param bufferSize 缓冲区大小cl
* @return 接收到的数据
*/
public byte[] receiveData(int bufferSize) {
if (serialPort == null || !serialPort.isOpen()) {
return null;
}
byte[] buffer = new byte[bufferSize];
int bytesRead = serialPort.readBytes(buffer, bufferSize);
if (bytesRead > 0) {
byte[] actualData = new byte[bytesRead];
System.arraycopy(buffer, 0, actualData, 0, bytesRead);
return actualData;
} else {
return null;
}
}
}
Controller
package com.xxxx.jserialcomm.controller;
import com.xxxx.jserialcomm.response.R;
import com.xxxx.jserialcomm.service.CommService;
import com.xxxx.jserialcomm.utils.DataChangeUtil;
import com.xxxx.jserialcomm.utils.SerialCommUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Api(value = "Java串口通讯测试")
public class SemeaController {
@Autowired
CommService commService;
public static SerialCommUtil serialCommUtil = SerialCommUtil.getSerialCommUtil();
@ApiOperation(value = "初始化串口")
@PostMapping("/init")
public R init(String portName, int baudRate) {
boolean flag = serialCommUtil.openPort(portName, baudRate);
if(flag){
return R.ok().data("msg","初始化成功");
}else{
return R.error().data("msg","初始化失败");
}
}
@ApiOperation(value = "向传感器发送消息")
@PostMapping("/sendMsg")
public R sendMsg( String message) {
boolean flag = serialCommUtil.sendData(message.getBytes());
if(flag){
return R.ok().data("msg","消息发送成功:"+ message);
}else{
return R.error().data("msg","消息发送失败");
}
}
@ApiOperation(value = "释放资源,关闭串口")
@PostMapping("/closePort")
public R closePort() {
boolean b = serialCommUtil.closePort();
if(b){
return R.ok();
}else {
return R.error();
}
}
}
作者:【AL】