这篇我将自己的源码放上来供大家参考。
准备工作1:
下载Virtual Serial Port Driver ,我用的是7.2版本,打开如图
这里我已经创建好虚拟端口COM1和COM2了,就不在新建端口了
准备工作2:
下载rxtx框架,http://fizzed.com/oss/rxtx-for-java
下载下来是可用的是一个jar包和两个dll
注意dll要放到jre的bin目录下,rxtx除了要引入工程中,还要放在jdk/jre/lib/ext文件夹一份,详情去看rxtx正确的使用方式
3.串口调试助手
我用的是友善串口调试助手,网上应该很好下,打开即用,界面如下。串口调试助手用来验证你的发送和接收数据是否成功。
做好这些,准备工作就完成啦,我们开始建工程。
下图是工程目录,别被这么多源文件吓到了,大部分是自定义异常(我要知道连不上串口或者发不出信息或者接收不到信息的原因在哪),真正有用的类是SerialTool.java(工具类)和client.java(测试类)
下面上源码,首先是工具类:
package 测试串口;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.TooManyListenersException;
import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import gnu.io.UnsupportedCommOperationException;
public class SerialTool {
/**
* 查找所有可用端口
* @return 可用端口名称列表
*/
public static final ArrayList findPort() {
//获得当前所有可用串口
@SuppressWarnings("unchecked")
Enumeration portList = CommPortIdentifier.getPortIdentifiers();
ArrayList portNameList = new ArrayList();
//将可用串口名添加到List并返回该List
while (portList.hasMoreElements()) {
String portName = portList.nextElement().getName();
portNameList.add(portName);
}
return portNameList;
}
/**
* 打开串口
* @param portName 端口名称
* @param baudrate 波特率
* @return 串口对象
* @throws SerialPortParameterFailure 设置串口参数失败
* @throws NotASerialPort 端口指向设备不是串口类型
* @throws NoSuchPort 没有该端口对应的串口设备
* @throws PortInUse 端口已被占用
*/
public static final SerialPort openPort(String portName, int baudrate) throws SerialPortParameterFailure, NotASerialPort, NoSuchPort, PortInUse {
try {
//通过端口名识别端口
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
//打开端口,并给端口名字和一个timeout(打开操作的超时时间)
CommPort commPort = portIdentifier.open(portName, 2000);
//判断是不是串口
if (commPort instanceof SerialPort) {
SerialPort serialPort = (SerialPort) commPort;
try {
//设置一下串口的波特率等参数
serialPort.setSerialPortParams(baudrate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
/*serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);*/
} catch (UnsupportedCommOperationException e) {
throw new SerialPortParameterFailure();
}
System.out.println("Open " + portName + " successfully !");
return serialPort;
}
else {
//不是串口
throw new NotASerialPort();
}
} catch (NoSuchPortException e1) {
throw new NoSuchPort();
} catch (PortInUseException e2) {
throw new PortInUse();
}
}
/**
* 关闭串口
* @param serialport 待关闭的串口对象
*/
public static void closePort(SerialPort serialPort) {
if (serialPort != null) {
serialPort.close();
serialPort = null;
}
}
/**
* 往串口发送数据
* @param serialPort 串口对象
* @param order 待发送数据
* @throws SendDataToSerialPortFailure 向串口发送数据失败
* @throws SerialPortOutputStreamCloseFailure 关闭串口对象的输出流出错
*/
public static void sendToPort(SerialPort serialPort, byte[] order) throws SendDataToSerialPortFailure, SerialPortOutputStreamCloseFailure {
OutputStream out = null;
try {
out = serialPort.getOutputStream();
out.write(order);
out.flush();
System.out.println("写入成功");
} catch (IOException e) {
throw new SendDataToSerialPortFailure();
} finally {
try {
if (out != null) {
out.close();
out = null;
}
} catch (IOException e) {
throw new SerialPortOutputStreamCloseFailure();
}
}
}
/**
* 从串口读取数据
* @param serialPort 当前已建立连接的SerialPort对象
* @return 读取到的数据
* @throws ReadDataFromSerialPortFailure 从串口读取数据时出错
* @throws SerialPortInputStreamCloseFailure 关闭串口对象输入流出错
*/
public static byte[] readFromPort(SerialPort serialPort) throws ReadDataFromSerialPortFailure, SerialPortInputStreamCloseFailure {
InputStream in = null;
byte[] bytes = null;
try {
in = serialPort.getInputStream();
int bufflenth = in.available(); //获取buffer里的数据长度
while (bufflenth != 0) {
bytes = new byte[bufflenth]; //初始化byte数组为buffer中数据的长度
in.read(bytes);
bufflenth = in.available();
}
} catch (IOException e) {
throw new ReadDataFromSerialPortFailure();
} finally {
try {
if (in != null) {
in.close();
in = null;
}
} catch(IOException e) {
throw new SerialPortInputStreamCloseFailure();
}
}
System.out.println("读取成功");
return bytes;
}
/**
* 添加监听器
* @param port 串口对象
* @param listener 串口监听器
* @throws TooManyListeners 监听类对象过多
*/
public static void addListener(SerialPort port, DataAvailableListener listener) throws TooManyListeners {
try {
//给串口添加监听器
port.addEventListener(new SerialPortListener(listener));
//设置当有数据到达时唤醒监听接收线程
port.notifyOnDataAvailable(true);
//设置当通信中断时唤醒中断线程
port.notifyOnBreakInterrupt(true);
} catch (TooManyListenersException e) {
throw new TooManyListeners();
}
}
/**
* 串口监听
*/
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.通讯中断
System.out.println("与串口设备通讯中断");
break;
default:
break;
}
}
}
/**
* 串口存在有效数据监听
*/
public interface DataAvailableListener {
/**
* 串口存在有效数据
*/
void dataAvailable();
}
}
自定义异常贴两个就行了,其他异常你们仿写下,异常类的名字都在工具类里。
不匹配异常
package 测试串口;
public class NoSuchPort extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public String toString() {
return "没有该端口对应的串口设备!";
}
}
串口设置异常
package 测试串口;
public class SerialPortParameterFailure extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
public SerialPortParameterFailure() {}
@Override
public String toString() {
return "设置串口参数失败!打开串口操作未完成!";
}
}
最后贴下测试类和运行结果
package 测试串口;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Locale;
import gnu.io.SerialPort;
public class client {
public static void main(String[] args) throws SerialPortParameterFailure, NotASerialPort, NoSuchPort, PortInUse, SendDataToSerialPortFailure, SerialPortOutputStreamCloseFailure, ReadDataFromSerialPortFailure, SerialPortInputStreamCloseFailure, TooManyListeners {
ArrayList findPort = SerialTool.findPort();
System.out.println("可用串口");
for(String f:findPort) {
System.out.println(f);
}
System.out.println();
//设定发送字符串
byte[] bs = hex2Bytes("AA");
System.out.println(Arrays.toString(bs));//打印字符串
System.out.println(findPort.get(0));//找到COM1串口
SerialPort Port = SerialTool.openPort("COM1", 9600);//打开串口
System.out.println(Port.getName());//获取串口名
SerialTool.addListener(Port, new SerialTool.DataAvailableListener() {
@SuppressWarnings("unused")
@Override
public void dataAvailable() {
byte[] data = null;
try {
if (Port == null) {
System.out.println("串口对象为空,监听失败!");
} else {
// 读取串口数据
data = SerialTool.readFromPort(Port);
/*System.out.println("打印"+data);*/
String resultHEX = byteArrayToHexString(data);
System.out.println(resultHEX);
}
} catch (Exception e) {
System.out.println("错误");
}
}
});
SerialTool.sendToPort(Port, bs);//写入,写入应该在监听器打开之后而不是之前
/*byte[] readFromPort = SerialTool.readFromPort(Port);
System.out.println(readFromPort);*/
/*SerialTool.closePort(Port);*/
}
public static byte[] hex2Bytes(String hex) {
if (hex == null || hex.length() == 0) {
return null;
}
char[] hexChars = hex.toCharArray();
byte[] bytes = new byte[hexChars.length / 2]; // 如果 hex 中的字符不是偶数个, 则忽略最后一个
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) Integer.parseInt("" + hexChars[i * 2] + hexChars[i * 2 + 1], 16);
}
return bytes;
}
/**
* byte[]转十六进制字符串
*
* @param array
* byte[]
* @return 十六进制字符串
*/
public static String byteArrayToHexString(byte[] array) {
if (array == null) {
return "";
}
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < array.length; i++) {
buffer.append(byteToHex(array[i]));
}
return buffer.toString();
}
/**
* byte转十六进制字符
*
* @param b
* byte
* @return 十六进制字符
*/
public static String byteToHex(byte b) {
String hex = Integer.toHexString(b & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
return hex.toUpperCase(Locale.getDefault());
}
}
测试结果:
如果有帮助,点个❤吧