- 还是半年前接触的JAVA串口编程控制硬件,现在项目中又即将运用到,所以特别写成博客记录,同时分享交流。
- Java环境中的JDK是本身不带有串口的jar包的,需要我们自己下载然后配置到本地的JDK之中,我们采用RXTX串口包(sun公司也提供了一个串口包但是十多年没更新了,不支持64位机器),RXTX是另外一个公司提供的,支持Windows和linux的。
官网下载地址:http://fizzed.com/oss/rxtx-for-java
自己选择版本下载压缩包,然后解压。我们这里用Windows64位的,解压后如下图
将这个配置到本地JDK中,步骤如下:
复制 RXTXcomm.jar —> <JAVA_HOME>\jre\lib\ext
复制 rxtxSerial.dll —> <JAVA_HOME>\jre\bin
复制 rxtxParallel.dll —> <JAVA_HOME>\jre\bin
注意:是JAVA_HOME里面的jdk目录,不是jre的目录
如我的是:
安装好本地JDK串口环境我们就可以在项目中使用了。
将需要控制的USB串口设备连接到你的电脑上,然后我们电脑上就会多一个串口,我们需要知道它的串口名字。
查看串口步骤:
计算机(我的电脑)–右键–管理–设备管理器–端口 如下图:
COM3就是我们插入的USB串口名字,我们在后面的代码中就是要根据这个COM3串口名对其进行硬件的控制。
import gnu.io.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
/**
* 警灯控制类 方法包括 init(PortName)初始化串口
* closeSerialPort()关闭串口
* openLamp(int second)开启警灯 到时间自动关闭
* closeLamp()关闭警灯
* <p>
* 说明:无论是开启警灯和关闭警灯都需要先进行初始化串口
*/
// 注:串口操作类一定要实现SerialPortEventListener
public class lamp implements SerialPortEventListener {
// 检测系统中可用的通讯端口类
private CommPortIdentifier portId;
// 枚举类型
private Enumeration<CommPortIdentifier> portList;
// RS232串口
private SerialPort serialPort;
// 输入输出流
private InputStream inputStream;
private OutputStream outputStream;
//实现接口SerialPortEventListener中的方法
@Override
public void serialEvent(SerialPortEvent serialPortEvent) {
switch (serialPortEvent.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: //有数据到达
break;
default:
break;
}
}
/**
* 初始化 需要把串口名传入
*/
public String init(String PortName0) {
//获取系统中所有的通讯端口
portList = CommPortIdentifier.getPortIdentifiers();
//把串口名进行优化,默认自动转成大写 让其传入值可忽略大小写
String PortName = PortName0.toUpperCase();
// 循环通讯端口
while (portList.hasMoreElements()) {
portId = portList.nextElement();
// 判断是否是串口
if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
// 比较串口名称是否是我们所要的那个
if (PortName.equals(portId.getName())) {
System.out.println("找到警灯串口" + PortName);
try {
//如果确实是我们需要的串口,则打开这个串口
// 并且需要转化成非抽象的serialPort类才能进行操作
serialPort = (SerialPort) portId.open(Object.class.getSimpleName(), 2000);
System.out.println("获取到警灯串口对象," + PortName);
//获取输入输出流
outputStream = serialPort.getOutputStream();
inputStream = serialPort.getInputStream();
// 设置串口通讯参数
// 波特率,数据位,停止位和校验方式
// 波特率2400,偶校验
serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8,//
SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
return "初始化成功";
} catch (PortInUseException e) {
System.out.println("该串口已经被占用");
} catch (UnsupportedCommOperationException e) {
System.out.println("为发现该串口");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
return null;
}
/**
* 关闭串口
*/
public void closeSerialPort() {
if (serialPort != null) {
serialPort.notifyOnDataAvailable(false);
serialPort.removeEventListener();
if (inputStream != null) {
try {
inputStream.close();
inputStream = null;
} catch (IOException e) {
}
}
if (outputStream != null) {
try {
outputStream.close();
outputStream = null;
} catch (IOException e) {
}
}
serialPort.close();
System.out.println("串口已关闭");
serialPort = null;
}
}
//------------------------------------下面是我自己写的,用来控制警灯的------------------------------------
/**
* 打开警灯 需要传入时间 单位:秒 当为0时则一直开启 不会自动关闭
*
* 到时间后警灯会自动关闭
*
* @param second
*/
public void openLamp(int second) {
//如果传入时间为0则默认一直开启 不会自动关闭
String msg = "FE050000FF009835";//要发送的命令msg
try {
outputStream.write(hexStringToBytes(msg));
System.out.println("警灯已开启");
if(second!=0){
try {
Thread.sleep(1000*second);
closeLamp();
System.out.println("警灯已关闭");
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
//控制硬件基本都是16+进制,发送指令的时候需要16进制转成字节数组
//将输入的16进制string转成字节
public static byte[] hexStringToBytes(String hexString) {
if (hexString == null || hexString.equals("")) {
return null;
}
hexString = hexString.toUpperCase();
int length = hexString.length() / 2;
char[] hexChars = hexString.toCharArray();
byte[] d = new byte[length];
for (int i = 0; i < length; i++) {
int pos = i * 2;
d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
}
return d;
}
private static byte charToByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}
/**
* 关闭警灯
*
*/
public void closeLamp() {
//发送关闭警灯的命令
String msg = "FE0500000000D9C5";
try {
outputStream.write(hexStringToBytes(msg));
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("警灯已关闭");
}
//-----------------------------------自己写的结束------------------------------------
}
测试类:
/**
*
* 警灯串口测试类
*
* */
public class lampTest1{
public static void main(String[] args) {
//实例化串口对象
lamp lamp=new lamp();
//传入串口名进行初始化 忽略大小写
String com = lamp.init("com3");
if(com!=null &&!"".equals(com)){
//打开警灯 传入开启时间,到时间后自动关闭 单位为秒 如果为0则默认一直开启 不会自动关闭
lamp.openLamp(5);
// lamp.closeLamp();
}else {
System.out.println("初始化失败,请检查串口名是否错误或该串口是否存在");
}
lamp.closeSerialPort();
}
}
注意:发送什么指令需要你根据硬件的产品说明书来!!!!,每个产品是不一样的
到此就完成了连接串口设备,并发送指定操作的程序,如果需要进一步操作,比如对设备返回的数据进行获取操作的话,继续下面代码
其他深入操作:
对串口读:
SerialPortSimpleRead类
/*
* @(#)SimpleRead.java 1.12 98/06/25 SMI
*
* Copyright (c) 1998 Sun Microsystems, Inc. All Rights Reserved.
*
* Sun grants you ("Licensee") a non-exclusive, royalty free, license
* to use, modify and redistribute this software in source and binary
* code form, provided that i) this copyright notice and license appear
* on all copies of the software; and ii) Licensee does not utilize the
* software in a manner which is disparaging to Sun.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND
* ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
* LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE
* SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS
* BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES,
* HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING
* OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* This software is not designed or intended for use in on-line control
* of aircraft, air traffic, aircraft navigation or aircraft
* communications; or in the design, construction, operation or
* maintenance of any nuclear facility. Licensee represents and
* warrants that it will not use or redistribute the Software for such
* purposes.
*/
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.TooManyListenersException;
/**
* * 该类用来接收串口数据,并在新线程中处理
* * 使用时如果需要对接收的进行数据处理,必须重写serialEvent(SerialPortEvent event)方法
* @author zhe
*
*/
public class SerialPortSimpleRead implements Runnable, SerialPortEventListener {
Logger logger = LoggerFactory.getLogger(this.getClass());
InputStream inputStream;
SerialPort serialPort;
public Thread readThread;
private boolean isSingleMessage = true;
//回传对象
SerialPortManager serialPortManager;
private String readStr = "";
//串口参数
int bautrate;
int SerialPort_DATABIT;
int SerialPort_STOPBIT;
int SerialPort_PARITY;
/**
* 创建读取串口对象
* @param serialPort 端口号的字符串,如:"COM5"
* @param serialPortManager
* @param isSingleMessage
*/
public SerialPortSimpleRead(SerialPort serialPort, SerialPortManager serialPortManager, boolean isSingleMessage) {
System.out.println("创建接收对象");
this.serialPort = serialPort;
this.serialPortManager = serialPortManager;
this.isSingleMessage = isSingleMessage;
try {
inputStream = serialPort.getInputStream();
} catch (IOException e) {}
try {
serialPort.addEventListener(this);
} catch (TooManyListenersException e) {
}
serialPort.notifyOnDataAvailable(true);
// try {
// serialPort.setSerialPortParams(115200,
// SerialPort.DATABITS_8,
// SerialPort.STOPBITS_1,
// SerialPort.PARITY_NONE);
// } catch (UnsupportedCommOperationException e) {}
//readThread = new Thread(this);
//readThread.start();
}
@Override
public void run() {
try {
Thread.sleep(20000);
logger.info("串口接收二十秒超时,退出……");
} catch (InterruptedException e) {
logger.error("InterruptedException", e);
}
}
@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:
byte[] readBuffer = new byte[128];
try {
while (inputStream.available() > 0) {
int numBytes = inputStream.read(readBuffer);
byte[] realBytes = new byte[numBytes];
System.arraycopy(readBuffer, 0, realBytes, 0, numBytes);
String receivedStr = encode(realBytes);
//单条消息通过回调就能处理
if (isSingleMessage){
serialPortManager.serialReadNotify(receivedStr);
readStr = receivedStr;
} else {//非单条消息定时处理
readStr = readStr + receivedStr;
}
}
} catch (IOException e) {
logger.error("inputStream read error.", e);
}
break;
}
}
public static String hexStringToString(String s) {
if (s == null || s.equals("")) {
return null;
}
s = s.replace(" ", "");
byte[] baKeyword = new byte[s.length() / 2];
for (int i = 0; i < baKeyword.length; i++) {
try {
baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16));
} catch (Exception e) {
e.printStackTrace();
}
}
try {
s = new String(baKeyword, "UTF-8");
new String();
} catch (Exception e1) {
e1.printStackTrace();
}
return s;
}
/**
* 16进制数字字符集
*/
private static String hexString = "0123456789ABCDEF";
/*
* 将字符串编码成16进制数字,适用于所有字符(包括中文)
*/
public static String encode(byte[] str) {
// 根据默认编码获取字节数组
byte[] bytes = str;
StringBuilder sb = new StringBuilder(bytes.length * 2);
// 将字节数组中每个字节拆解成2位16进制整数
for (int i = 0; i < bytes.length; i++) {
sb.append(hexString.charAt((bytes[i] & 0xf0) >> 4));
sb.append(hexString.charAt((bytes[i] & 0x0f) >> 0));
}
return sb.toString();
}
/**
* 释放掉资源
*/
public void close(){
if(readThread!=null){
readThread.interrupt();;
readThread = null;
}
if(serialPort!=null){
serialPort.close();
serialPort=null;
}
if(inputStream!=null){
try {
inputStream.close();
inputStream = null;
} catch (IOException e) {
logger.error("inputStream.close error.", e);
}
}
}
public String getReadStr() {
return readStr;
}
public void setReadStr(String readStr) {
this.readStr = readStr;
}
}
对串口写:
SerialPortSimpleWrite类
/*
* @(#)SimpleWrite.java 1.12 98/06/25 SMI
*
* Copyright (c) 1998 Sun Microsystems, Inc. All Rights Reserved.
*
* Sun grants you ("Licensee") a non-exclusive, royalty free, license
* to use, modify and redistribute this software in source and binary
* code form, provided that i) this copyright notice and license appear
* on all copies of the software; and ii) Licensee does not utilize the
* software in a manner which is disparaging to Sun.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND
* ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
* LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE
* SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS
* BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES,
* HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING
* OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* This software is not designed or intended for use in on-line control
* of aircraft, air traffic, aircraft navigation or aircraft
* communications; or in the design, construction, operation or
* maintenance of any nuclear facility. Licensee represents and
* warrants that it will not use or redistribute the Software for such
* purposes.
*/
import gnu.io.SerialPort;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
public class SerialPortSimpleWrite {
Logger logger = LoggerFactory.getLogger(this.getClass());
SerialPort serialPort;
public OutputStream outputStream;
/**
* 创建串口写数据对象
* @param serialPort 窗口号字符串,如:"COM5"
*/
public SerialPortSimpleWrite(SerialPort serialPort) {
//super();
this.serialPort = serialPort;
try {
this.outputStream = serialPort.getOutputStream();
} catch (IOException e) {
logger.error("serialPort[{}] create SerialPortSimpleWrite error.", serialPort.getName(), e);
}
}
/**
* 串口输出一个字符
* @param ch
*/
public void write(int ch){
try {
outputStream.write(ch);
} catch (IOException e) {
logger.error("serail write error.", e);
}
}
/**
* 给下位机单片机发送一行字符
* @param datastr
*/
public void writeString(String datastr){
try {
outputStream.write(datastr.getBytes());
} catch (IOException e) {
logger.error("serail writeString error.", e);
}
}
/**
* 发送字符串给STM32F4
* @param datastr
* @param loopdelay 下位机串口轮询的周期,单位ms
*/
public void writeStringToSTM32(String datastr, int loopdelay){
try {
datastr = datastr.replaceAll(" ", "");
//发送
logger.info("发送数据 data[{}], 16进制[{}] loopdelay[{}ms]", new String[]{ datastr, new String(hex2byte(datastr)), loopdelay + ""});
outputStream.write(hex2byte(datastr));
Thread.sleep(loopdelay);
} catch (Exception e) {
logger.error("writeStringToSTM32 error.", e);
}
}
public static byte[] hex2byte(String hex) {
String digital = "0123456789ABCDEF";
String hex1 = hex.replace(" ", "");
char[] hex2char = hex1.toCharArray();
byte[] bytes = new byte[hex1.length() / 2];
byte temp;
for (int p = 0; p < bytes.length; p++) {
temp = (byte) (digital.indexOf(hex2char[2 * p]) * 16);
temp += digital.indexOf(hex2char[2 * p + 1]);
bytes[p] = (byte) (temp & 0xff);
}
return bytes;
}
/**
* 发送文件给STM32,读出文本内容分行发给STM32
* @param file 要传送文本文件
* @param loopdelay
*/
public void writeFileToSTM32(final File file , final int loopdelay){
Thread sendfileThread = new Thread(){
public void run() {
try {
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
String line = null;
while((line = br.readLine())!=null){
System.out.println("发送:"+line);
//发送一行
writeStringToSTM32(line,loopdelay);
}
//发送结束标志"$$"
SerialPortSimpleWrite.this.writeString("$$sendover");
//延时
Thread.sleep(loopdelay);
br.close();
} catch (Exception e) {
e.printStackTrace();
}
}
};
sendfileThread.start();
}
/**
* 关闭串口资源
*/
public void close(){
if(outputStream != null){
try {
outputStream.close();
outputStream = null;
} catch (IOException e) {
logger.error("outputStream close error.", e);
}
}
if(serialPort != null){
serialPort.close();
}
}
}
管理串口数据收发的类:
SerialPortManager
import com.alibaba.fastjson.JSON;
import gnu.io.CommPortIdentifier;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.UnsupportedCommOperationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.TooManyListenersException;
/**
* 该类是用来管理串口数据收发的类,通过该类的静态方法可以获取系统可识别的端口
* 使用时如果需要对接收的数据进行处理,处理代码添加在getPortSimpleReadInstance()中的serialEvent(SerialPortEvent event)方法
*
*
*/
public abstract class SerialPortManager {
static Logger logger = LoggerFactory.getLogger("serial");
//定义串口收发变量
private SerialPortSimpleRead portSimpleRead;
private SerialPortSimpleWrite portSimpleWrite;
@SuppressWarnings("rawtypes")
static Enumeration portList;
static CommPortIdentifier portId;
static SerialPort serialPort;
//通讯参数 默认值如下
int bautrate = 9600;
int serialPort_DATABIT = SerialPort.DATABITS_8;
int serialPort_STOPBIT = SerialPort.STOPBITS_1;
int serialPort_PARITY = SerialPort.PARITY_NONE;
static{
//获取系统COM列表
portList = CommPortIdentifier.getPortIdentifiers();
}
/**
* 用指定参数构造
* @param comPort
* @param bautrate
* @param serialPort_DATABIT
* @param serialPort_STOPBIT
* @param serialPort_PARITY
*/
public SerialPortManager(String comPort, int bautrate, int serialPort_DATABIT,
int serialPort_STOPBIT, int serialPort_PARITY, boolean isSingleMessage, boolean isOpenReadThread, boolean isOpenWriteThread) {
this.bautrate = bautrate;
this.serialPort_DATABIT = serialPort_DATABIT;
this.serialPort_STOPBIT = serialPort_STOPBIT;
this.serialPort_PARITY = serialPort_PARITY;
SerialPortManager.serialPort = openPort(comPort, isSingleMessage, isOpenReadThread, isOpenWriteThread);
}
/**
* 默认参数构造
* @param comPort
* @throws TooManyListenersException
*/
public SerialPortManager(String comPort, boolean isSingleMessage, boolean isOpenReadThread, boolean isOpenWriteThread) {
super();
//设置要管理的端口,打开串口
SerialPortManager.serialPort = openPort(comPort, isSingleMessage, isOpenReadThread, isOpenWriteThread);
}
/**
* 以字符串集合的方式返回当前系统可识别的串口(COM)号
* @return 端口号的字符集合
*/
public synchronized static List<String> getAvailablePorts(){
//重新获取系统COM列表
portList = CommPortIdentifier.getPortIdentifiers();
//列表保存成字符串集合
List<String> portstrList = new ArrayList<>();
//遍历集合
while (portList.hasMoreElements()) {
portId = (CommPortIdentifier) portList.nextElement();
//如果端口是串口
if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
logger.info("获取到的串口ID[{}], info[{}]", portId.getName(), JSON.toJSONString(portId));
//添加到集合
portstrList.add(portId.getName());
}
}
return portstrList;
}
/**
* 打开串口
* @param comPort 端口号字符串 ,如:"COM5"
* @return 返回打开的串口
*/
private synchronized SerialPort openPort(String comPort, boolean isSingleMessage, boolean isOpenReadThread, boolean isOpenWriteThread){
//重新获取系统COM列表
portList = CommPortIdentifier.getPortIdentifiers();
if(portList.hasMoreElements()!=true){
logger.error("打开端口失败,检测不到串口[{}]", comPort);
return null;
}
SerialPort serialPort = null;
//遍历集合
while (portList.hasMoreElements()) {
portId = (CommPortIdentifier) portList.nextElement();
if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
logger.info("获取到的串口[{}]", portId.getName());
if (portId.getName().equals(comPort)){
try {
serialPort = (SerialPort) portId.open("SerialPortManager", 2000);
serialPort.setSerialPortParams(this.bautrate,
this.serialPort_DATABIT,
this.serialPort_STOPBIT,
this.serialPort_PARITY);
} catch (PortInUseException e) {
logger.error("串口[{}]被占用", portId.getName());
} catch (UnsupportedCommOperationException e) {
logger.error("串口[{}]设置的参数不支持", portId.getName(), e);
} catch (Exception e) {
logger.error("串口[{}]打开异常", portId.getName(), e);
}
}
}
}
if (serialPort == null){
logger.error("串口[{}]打开失败!", comPort);
return null;
}
if (isOpenReadThread ){
//开启一个接收线程
portSimpleRead = new SerialPortSimpleRead(serialPort, this, isSingleMessage);
logger.info("串口[{}]----开启接收线程", comPort);
}
if (isOpenWriteThread && serialPort != null){
portSimpleWrite = new SerialPortSimpleWrite(serialPort);
logger.info("串口[{}]----开启发送线程", comPort);
}
return serialPort;
}
/**
* 根据新参数再次打开 串口
* @param comPort
* @param isSingleMessage
* @param isOpenReadThread
* @param isOpenWriteThread
* @return
*/
public synchronized SerialPort reOpenPort(String comPort, boolean isSingleMessage, boolean isOpenReadThread, boolean isOpenWriteThread){
//关闭当前串口
close();
SerialPortManager.serialPort = openPort(comPort, isSingleMessage, isOpenReadThread, isOpenWriteThread);
logger.info("串口重启成功----");
return serialPort;
}
/**
* 设置串口参数
* @param bautrate
* @param serialPort_DATABIT
* @param serialPort_STOPBIT
* @param serialPort_PARITY
*/
void setCommPrams(int bautrate,
int serialPort_DATABIT,
int serialPort_STOPBIT,
int serialPort_PARITY){
this.bautrate = bautrate;
this.serialPort_DATABIT = serialPort_DATABIT;
this.serialPort_STOPBIT = serialPort_STOPBIT;
this.serialPort_PARITY = serialPort_PARITY;
}
/**
* 关闭串口管理的资源
*/
public synchronized void close(){
try {
String portName = null;
if (serialPort != null){
portName = serialPort.getName();
}
logger.info("-----串口[{}]关闭-----", portName);
if(SerialPortManager.serialPort!=null){
SerialPortManager.serialPort.close();
serialPort = null;
}
if (portSimpleRead != null){
logger.info("-----串口[{}]关闭读线程-----", portName);
portSimpleRead.close();
}
if (portSimpleWrite != null){
logger.info("-----串口[{}]关闭写线程-----", portName);
portSimpleWrite.close();
}
} catch (Exception e) {
logger.error("close失败", e);
}
}
/**
* 处理串口读到数据后怎么处理
* @param readStr
*/
public abstract void serialReadNotify(String readStr);
public SerialPortSimpleRead getPortSimpleRead() {
return portSimpleRead;
}
public void setPortSimpleRead(SerialPortSimpleRead portSimpleRead) {
this.portSimpleRead = portSimpleRead;
}
public SerialPortSimpleWrite getPortSimpleWrite() {
return portSimpleWrite;
}
public void setPortSimpleWrite(SerialPortSimpleWrite portSimpleWrite) {
this.portSimpleWrite = portSimpleWrite;
}
}
测试
测试类:SerialPortManagerTest
import cn.hutool.core.util.StrUtil;
import com.example.demo2.serial.SerialPortManager;
import com.example.demo2.serial.SerialPortSimpleRead;
import com.example.demo2.serial.SerialPortSimpleWrite;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
public class SerialPortManagerTest {
static Logger logger = LoggerFactory.getLogger(SerialPortManagerTest.class);
public static void main2(String[] agrs){
//一般写测试
for (int i = 0; i < 10; i++){
SerialPortManager cabinetSerailManager = new SerialPortManager("COM3", false, true, true) {
//响应串口接收读数据
@Override
public void serialReadNotify(String readStr) {
//应用程序,监听到数据读入
System.out.println("应用程序,监听到数据读入:"+readStr);
//读数据测试
}
};
String message = "55 AA 01 0A 05 04 90 00 04 00 3F 68 86";
write(cabinetSerailManager.getPortSimpleWrite(), cabinetSerailManager.getPortSimpleRead(), message);
try {
Thread.sleep(500L);
} catch (InterruptedException e) {
logger.error("", e);
}
//关闭串口
cabinetSerailManager.close();
}
}
public static void main(String[] agrs) throws InterruptedException {
//一般写测试
SerialPortSimpleRead simpleRead;
SerialPortManager cabinetSerailManager = new SerialPortManager("COM4", true, true, false) {
//响应串口接收读数据
@Override
public void serialReadNotify(String message) {
String msgStr = SerialPortSimpleRead.hexStringToString(message);
//应用程序,监听到数据读入
logger.info("监听串口接收数据[{}]", msgStr.trim());
//调用后台程序
}
};
while(true){
if (!StrUtil.isEmpty(cabinetSerailManager.getPortSimpleRead().getReadStr())){
//System.out.println(simpleRead.getReadStr());
}
Thread.sleep(1000L);
}
//关闭串口
//cabinetSerailManager.close();
}
/**
* 获取系统可以识别的串口
* @return 返回端口的字符串集合
*/
public static List<String> getPortsList(){
List<String> list = SerialPortManager.getAvailablePorts();
return list;
}
/**
* 发送数据
*/
public synchronized static void write(final SerialPortSimpleWrite simpleWrite, final SerialPortSimpleRead simpleRead, String message){
simpleRead.setReadStr("");
simpleWrite.writeStringToSTM32(message, 1000);
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
String returnValue = simpleRead.getReadStr();
System.out.println("返回:" + returnValue);
}
}, 10);// 设定指定的时间time,此处为10毫秒
}
}
这些就包含了对串口的常用操作了,完结