1.准备工作
在进行串口连接通讯前,必须保证你当前操作电脑上有可用且闲置的串口。因为一般的电脑上只有一个或者两个串口,如COM1或COM2,但大多数情况下,这些串口可能会被其他的程序或者应用所占用,所以此时我们可以借助工具,在我们的电脑上建立虚拟串口。
先下载一个叫Virtual Serial Port的软件,通过这个软件可以创建新的虚拟串口,如下图所示:
通过图中的添加串口即可进行新虚拟串口的创建,并且一般都是成对创建。
有了虚拟串口之后,为了方便测试新建串口是否可用,我们可以再下载一款串口测试软件,我用的是一个串口调试助手,如下图:
通过测试,发现我所添加的虚拟串口COM3和COM4是可以用的,那么接下来,我们就可以关闭其中一个,通过我们的JAVA程序来进行与该虚拟串口的信息交互了。
2.JAVA程序的操作
在进行程序编写之前,我们需要下载几个文件,才能使我们的程序进行串口通讯的操作。
首先需要下载如下图中的三个文件:
并将RXTXcomm.jar这个包通过集成工具的构建路径添加到我们的项目之中;其次将 rxtxParallel.dll 和 rxtxSerial.dll 这两个文件放到我们的JDK安装目录中的bin文件夹中。
这两个文件必须添加到指定位置,否则后面程序在运行时将会报错找不到文件。(需要注意:这几个文件按操作系统分32位和64位,各位需要根据自己电脑的系统下载对应的版本,不然也会报错).
接下来可以开始我们的代码编写了,为了方便使用,我们肯定是需要有一个SerialPort串口工具类,如下:
-
package com.cams.CaMSMobileService.SerialPort;
-
-
import gnu.io.CommPort;
-
import gnu.io.CommPortIdentifier;
-
import gnu.io.NoSuchPortException;
-
import gnu.io.PortInUseException;
-
import gnu.io.SerialPort;
-
import gnu.io.SerialPortEventListener;
-
import gnu.io.UnsupportedCommOperationException;
-
-
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 com.cams.CaMSMobileService.SerialPort.exception.NoSuchPort;
-
import com.cams.CaMSMobileService.SerialPort.exception.NotASerialPort;
-
import com.cams.CaMSMobileService.SerialPort.exception.PortInUse;
-
import com.cams.CaMSMobileService.SerialPort.exception.ReadDataFromSerialPortFailure;
-
import com.cams.CaMSMobileService.SerialPort.exception.SendDataToSerialPortFailure;
-
import com.cams.CaMSMobileService.SerialPort.exception.SerialPortInputStreamCloseFailure;
-
import com.cams.CaMSMobileService.SerialPort.exception.SerialPortOutputStreamCloseFailure;
-
import com.cams.CaMSMobileService.SerialPort.exception.SerialPortParameterFailure;
-
import com.cams.CaMSMobileService.SerialPort.exception.TooManyListeners;
-
-
public class SerialPortManager {
-
-
/**
-
* 查找所有可用端口
-
*
-
* @return 可用端口名称列表
-
*/
-
-
public static final ArrayList<String> findPort() {
-
// 获得当前所有可用串口
-
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 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);
-
} catch (UnsupportedCommOperationException e) {
-
throw new SerialPortParameterFailure();
-
}
-
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();
-
} 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();
-
// 获取buffer里的数据长度
-
int bufflenth = in.available();
-
while (bufflenth != 0) {
-
// 初始化byte数组为buffer中数据的长度
-
bytes = new byte[bufflenth];
-
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();
-
}
-
}
-
return bytes;
-
}
-
-
/**
-
* 添加监听器
-
*
-
* @param port
-
* 串口对象
-
* @param listener
-
* 串口监听器
-
* @throws TooManyListeners
-
* 监听类对象过多
-
*/
-
public static void addListener(SerialPort port,
-
SerialPortEventListener listener) throws TooManyListeners {
-
try {
-
// 给串口添加监听器
-
port.addEventListener(listener);
-
// 设置当有数据到达时唤醒监听接收线程
-
port.notifyOnDataAvailable(true);
-
// 设置当通信中断时唤醒中断线程
-
port.notifyOnBreakInterrupt(true);
-
} catch (TooManyListenersException e) {
-
throw new TooManyListeners();
-
}
-
}
-
}
有了工具类之后,接下来我们就可以开始测试串口通讯了,如下:
到这里串口通讯测试的也差不多了。可能自己做的项目中需要自己做两个串口,一个client端和一个server端。为了使串口操作变的可视化,大家也可以使用JFrame来进行操作窗口模拟,这里就不做多的介绍了。