JAVA实现RS-485串口编程

近期开发过程中遇到需要读取底层传感器串口数据的问题,也是从无到有的一个过程,爬了不少帖子在这里记录一下,也给后来的朋友们一点小小的帮助吧。
下载链接在文末

串口介绍

如图所示就是一种串口转换器:
JAVA实现RS-485串口编程_第1张图片

Java对串口编程的API包

官方包:
1998年SUN发布的串口通信API:comm2.0.jar(Windows环境下)和comm3.0.jar(Linux/Solaris环境下);IBM发布的串口通信API;
但是sun已经停止了对commAPI的更新,现在使用的更多的是RXTX的jar包,下载链接百度RXTX官网就是

编程前准备

除了jar包以外,相信新出的台式电脑和笔记本电脑已经没有com接口了吧,在做测试之前我们选择虚拟两个串口出来,这里需要用到软件:vspdpro
后面我会整理出开发所需要的所有的软件,供大家下载的.

软件安装好以后,直接添加虚拟对就好了,选择你需要虚拟出的端口即可:
JAVA实现RS-485串口编程_第2张图片

开始编程

使用Eclipse工具,新建一个maven工程,添加pom依赖,代替手工导入RXTX.jar


		
			org.rxtx
			rxtx
			2.1.7
		

读取所有可用串口,并打印
这里我使用的端口是8和12大家可以灵活处理

package com.shenlan.demo485;



import java.util.Enumeration;

import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.UnsupportedCommOperationException;

public class RxtxDemo2 {
	public static void main(String[] args) {
		//定义表示端口的变量
		CommPortIdentifier portIdentifier = null;
		//定义记录每一个变量的枚举
		Enumeration portIdentifiers = CommPortIdentifier.getPortIdentifiers();
		//输出所有端口
		System.out.println("输出所有端口");
		while (portIdentifiers.hasMoreElements()) {
			portIdentifier  = (CommPortIdentifier) portIdentifiers.nextElement();
			System.out.println("串口:"+ portIdentifier.getName());
		}
		//获取两个端口
		CommPortIdentifier com8 =  null;
		CommPortIdentifier com12 =  null;
		try {
			com8 = CommPortIdentifier.getPortIdentifier("COM8");
			com12 = CommPortIdentifier.getPortIdentifier("COM12");
		} catch (NoSuchPortException  e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		//打开两个端口
		SerialPort serialCom8 = null;
		SerialPort serialCom12 = null;
		try {
			serialCom8=(SerialPort) com8.open("RxtxDemo2",1000);
			serialCom12=(SerialPort) com12.open("RxtxDemo2",1000);
		} catch (PortInUseException  e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		//设置端口参数
		try {
			serialCom8.setSerialPortParams(9600, //波特率
					SerialPort.DATABITS_8, //数据位 8
					SerialPort.STOPBITS_1,//停止位1 
					SerialPort.PARITY_NONE);//奇偶位
			serialCom12.setSerialPortParams(9600, //波特率
					SerialPort.DATABITS_8, //数据位 8
					SerialPort.STOPBITS_1,//停止位1 
					SerialPort.PARITY_NONE);//奇偶位
		} catch (UnsupportedCommOperationException  e) {
			// TODO: handle exception
			e.printStackTrace();
		//关闭端口8和12
			serialCom8.close();
			serialCom12.close();
		}
	}
}

完成对端口的打开和输出之后,我们还需要完成端口与端口之间的收发信息
这里需要用到一个软件,叫做端口调试助手,同样我也会打包上传的
这里通过轮询的方式监听COM15端口,与之相连的串口是COM8

package com.shenlan.demo485;

import java.io.IOException;
import java.io.InputStream;

import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;

public class Listener {
	/**
	 * 通过轮询模式监听串口COM15
	 * 当串口COM8传来数据的时候读取数据
	 */
	public static void main(String[] args) {
		CommPortIdentifier com15 = null;//定义需要接收数据的端口(未打开)
		SerialPort serialCom15 = null;//打开的端口
		InputStream inputStream = null;//端口输入流
		System.out.println("开始监听端口COM15收到的数据");
		try {
			//获取并打开串口com15
			com15 =CommPortIdentifier.getPortIdentifier("COM15");
			serialCom15 = (SerialPort) com15.open("Com15Listener", 1000);
			//System.out.println(serialCom15);
			//获取串口的输入流对象
			inputStream = serialCom15.getInputStream();
			//从串口读出数据
			//定义用于缓存读入数据的数组
			byte []cache = new byte[1024];
			//记录已经到达串口COM15且未被读取的数据的字节(Byte)数
			int availableBytes = 0;
			//通过无限循环的方式来扫描COM15,检查是否有数据到达端口,间隔20ms
			while (true) {
				//获取串口15收到的字节数
				availableBytes = inputStream.available();
				//如果可用字节数大于0则开始转换并获取数据
				while (availableBytes>0) {
				//从串口的输入流对象中读入数据并将数据存放到缓存数组中
					inputStream.read(cache);
					//将获取到的数据进行转码并输出
					for (int i = 0; i < cache.length&&i<availableBytes; i++) {
						System.out.print((char)cache[i]);
					}
					System.out.println();
					availableBytes = inputStream.available();
				}
				//线程睡眠20ms
				Thread.sleep(20);	
			}
		}catch(InterruptedException e){
			e.printStackTrace();
		}catch (NoSuchPortException e) {
			//找不到串口的情况下抛出该异常
			e.printStackTrace();
		} catch (PortInUseException e) {
			//如果因为端口被占用而导致打开失败,则抛出该异常
			e.printStackTrace();
		} catch (IOException e) {
			//如果获取输出流失败,则抛出该异常
			e.printStackTrace();
			}
	}
}

此时通过串口调试助手向COM15发送消息
选择com8-com15以后点击开始,然后单击发送
JAVA实现RS-485串口编程_第3张图片
COM15收到的消息被监听
JAVA实现RS-485串口编程_第4张图片
至此监听端口类书写完成

接下来完后端口对端口的发送:
COM15发送到COM8

package com.shenlan.demo485;



import java.io.IOException;
import java.io.OutputStream;

import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;

public class Write {
	/**
	 * 是向COM8发送数据
	 */
	public static void main(String[] args) {
		//定义变量
		CommPortIdentifier  com8 = null;
		SerialPort  serialCom8 = null;
		
		try {
			//获取com8端口
			com8 = CommPortIdentifier.getPortIdentifier("COM8");
			//打开com8端口
			serialCom8 = (SerialPort) com8.open("Com8Writer",1000);
			//写入数据
			//获取串口输出流对象
			OutputStream outputStream = serialCom8.getOutputStream();
			//通过串口的输出流向串口写数据
			byte hello[] = new byte[] {'H','e','l','l','o',' ','W','o','r','l','d','!'};
			outputStream.write(hello);
			/*
			 * 使用输出流往串口写数据的时候必须将数据转换为byte数组格式或int格式,
			 *  当另一个串口接收到数据之后再根据双方约定的规则,对数据进行解码
			 */
			//关闭输出流
			outputStream.flush();
			serialCom8.close();
			//关闭串口
		} catch (NoSuchPortException  e) {
			//找不到串口的情况下抛出该异常 exception
			e.printStackTrace();
		}catch (PortInUseException  e) {
			//如果因为端口被占用而导致打开失败,则抛出该异常
			e.printStackTrace();
		}catch (IOException e) {
			//如果获取输出流失败,则抛出该异常
			e.printStackTrace();
		}
	}
}

这里采用的是byte数组发送helloworld到端口,运行java类,可以在串口调试助手收到消息
JAVA实现RS-485串口编程_第5张图片
注意:这里调试的时候需要把端口更改为COM15-COM8,这样就能收到消息了.
简单的调试就到这里,稍后我上传源码和文件供大家下载,包括jar包和串口调试助手和虚拟串口的vspdpro
链接:百度网盘

链接:https://pan.baidu.com/s/1ogoSCmWoHDn7gnu8cK45Zw
提取码:4b93
复制这段内容后打开百度网盘手机App,操作更方便哦

源码:
https://download.csdn.net/download/weixin_43616450/11906730

你可能感兴趣的:(串口编程)