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来进行操作窗口模拟,这里就不做多的介绍了。