Java串口通信——RXTX
1.前期准备
a.配置 RXTX
1)下载 RXTX 包并解压,网址:http://fizzed.com/oss/rxtx-for-java
2)拷贝动态库到对应的jdk目录下
·Windows平台
拷贝 rxtxSerial.dll ---> <JAVA_HOME>\jre\bin
拷贝 rxtxParallel.dll ---> <JAVA_HOME>\jre\bin
·Linux平台
拷贝 librxtxSerial.so ---> <JAVA_HOME>/jre/lib/i386/
拷贝 librxtxParallel.so ---> <JAVA_HOME>/jre/lib/i386/
3)在工程根目录下创建 lib 文件夹(与src平级),将 RXTXcomm.jar 放入该文件夹中
4)在 pom.xml 中引入本地 jar 包依赖
<dependencies> ...... <dependency> <groupId>gnu.io</groupId> <artifactId>RXTXcomm</artifactId> <scope>system</scope> <systemPath>${project.basedir}/lib/RXTXcomm.jar</systemPath> </dependency> </dependencies>
b.安装虚拟串口驱动:vspd (收费,有破解版)
c.安装串口调试工具:Serial Port Utility (免费)
2.使用
a.新建串口VO类
public class SerialVo { /** * 串口名称(COM0、COM1、COM2等等) */ private String serialPortName; /** * 波特率 * 默认:115200 */ private int baudRate; /** * 数据位 默认8位 * 可以设置的值:SerialPort.DATABITS_5、SerialPort.DATABITS_6、SerialPort.DATABITS_7、SerialPort.DATABITS_8 * 默认:SerialPort.DATABITS_8 */ private int dataBits; /** * 停止位 * 可以设置的值:SerialPort.STOPBITS_1、SerialPort.STOPBITS_2、SerialPort.STOPBITS_1_5 * 默认:SerialPort.STOPBITS_1 */ private int stopBits; /** * 校验位 * 可以设置的值:SerialPort.PARITY_NONE、SerialPort.PARITY_ODD、SerialPort.PARITY_EVEN、SerialPort.PARITY_MARK、SerialPort.PARITY_SPACE * 默认:SerialPort.PARITY_NONE */ private int parity; public SerialVo(String serialPortName) { this.serialPortName = serialPortName; this.baudRate = 115200; this.dataBits = SerialPort.DATABITS_8; this.stopBits = SerialPort.STOPBITS_1; this.parity = SerialPort.PARITY_NONE; } public SerialVo(String serialPortName, int baudRate) { this.serialPortName = serialPortName; this.baudRate = baudRate; this.dataBits = SerialPort.DATABITS_8; this.stopBits = SerialPort.STOPBITS_1; this.parity = SerialPort.PARITY_NONE; } public String getSerialPortName() { return serialPortName; } public void setSerialPortName(String serialPortName) { this.serialPortName = serialPortName; } public int getBaudRate() { return baudRate; } public void setBaudRate(int baudRate) { this.baudRate = baudRate; } public int getDataBits() { return dataBits; } public void setDataBits(int dataBits) { this.dataBits = dataBits; } public int getStopBits() { return stopBits; } public void setStopBits(int stopBits) { this.stopBits = stopBits; } public int getParity() { return parity; } public void setParity(int parity) { this.parity = parity; } }
b.新建串口工具类
public class SerialUtil { /** * 获得系统可用的端口名称列表(COM0、COM1、COM2等等) */ public static List<String> getSerialPortList() { List<String> systemPorts = new ArrayList<>(); //获得系统可用的端口 Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers(); while (portList.hasMoreElements()) { String portName = portList.nextElement().getName();//获得端口的名字 systemPorts.add(portName); } return systemPorts; } /** * 打开串口 */ public static SerialPort openSerialPort(SerialVo serialVo, int timeout) throws Exception { //通过端口名称得到端口 CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(serialVo.getSerialPortName()); //打开端口,(自定义名字,打开超时时间) CommPort commPort = portIdentifier.open(serialVo.getSerialPortName(), timeout); //判断是不是串口 if (commPort instanceof SerialPort) { SerialPort serialPort = (SerialPort) commPort; //设置串口参数(波特率,数据位8,停止位1,校验位无) serialPort.setSerialPortParams(serialVo.getBaudRate(), serialVo.getDataBits(), serialVo.getStopBits(), serialVo.getParity()); System.out.println("开启串口成功,串口名称:" + serialVo.getSerialPortName()); return serialPort; } else { //是其他类型的端口 throw new NoSuchPortException(); } } /** * 关闭串口 */ public static void closeSerialPort(SerialPort serialPort) { if (serialPort != null) { serialPort.close(); System.out.println("关闭了串口:" + serialPort.getName()); } } /** * 向串口发送数据 */ public static void sendData(SerialPort serialPort, byte[] data) { OutputStream os = null; try { //获得串口的输出流 os = serialPort.getOutputStream(); os.write(data); os.flush(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (os != null) { os.close(); } } catch (IOException e) { e.printStackTrace(); } } } /** * 从串口读取数据 */ public static byte[] readData(SerialPort serialPort) { InputStream is = null; byte[] bytes = null; try { //获得串口的输入流 is = serialPort.getInputStream(); //获得数据长度 int bufflenth = is.available(); while (bufflenth != 0) { //初始化byte数组 bytes = new byte[bufflenth]; is.read(bytes); bufflenth = is.available(); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (is != null) { is.close(); } } catch (IOException e) { e.printStackTrace(); } } return bytes; } /** * 给串口设置监听 */ public static void setListenerToSerialPort(SerialPort serialPort, SerialPortEventListener listener) throws Exception { //给串口添加事件监听 serialPort.addEventListener(listener); //串口有数据监听 serialPort.notifyOnDataAvailable(true); //中断事件监听 serialPort.notifyOnBreakInterrupt(true); } }
3.调试
a.新建测试类
public class App { //防止被GC回收 private static SerialVo serialVo; public static void main( String[] args ) { //获得系统可用的端口名称 List<String> portList = SerialUtil.getSerialPortList(); System.out.println(portList); try { serialVo = new SerialVo("COM2"); final SerialPort serialPort = SerialUtil.openSerialPort(serialVo, 115200); //启动一个线程每2s向串口发送数据,发送1000次hello new Thread(() -> { int i = 1; while (i < 1000) { String s = "hello " + i++; byte[] bytes = s.getBytes(); SerialUtil.sendData(serialPort, bytes);//发送数据 try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); //设置串口的listener SerialUtil.setListenerToSerialPort(serialPort, event -> { //数据通知 if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) { byte[] bytes = SerialUtil.readData(serialPort); System.out.println("收到的数据长度:" + bytes.length); System.out.println("收到的数据:" + new String(bytes)); } }); } catch (Exception e) { e.printStackTrace(); } } }
b.使用 vspd 添加两个虚拟串口 COM2 和 COM3
c.使用 Serial Port Utility 测试串口的收发
d.注意:vspd 添加的虚拟串口为 COM2 和 COM3,Java代码中连接的是 COM2,则 Serial Port Utility 需连接 COM3。
4.参考文章
https://www.jianshu.com/p/7c03ad8a6139