有句话说的是"程序员的肚是杂货铺,什么都得有",近期项目中有使用到串口通讯,what ? 串口是什么鬼???感觉应该不是新技术吧? 对于现在整天使用框架、架构、构件什么的,突然要搞串口这个问题感到有些棘手,但是呢,牢骚、废话都没用,接下来开始搞。
首先了解一下什么是串口,找到了这么一个解释: 串口全称为串行接口,一般指COM接口,是采用串行通信方式的扩展接口。其特点是数据位的传送按位顺序进行,最少只需一根传输线即可完成,成本低但传送速度慢。由于串口(COM)不支持热插拔及传输速率较低,目前部分新主板和大部分便携电脑已取消该接口。现在串口多用于工业控制和测量设备以及部分通信设备中。 嗯 确实是现在使用串口的地方有些少了 , 但是项目中既然涉及到了就要简单了解一下 , 所以又给自己补了一下课,串口的图片是这样子的:
对于串口的了解就到这里吧 , 至于再有什么RS-485、RS-232就再自行百度吧 !!! 毕竟这篇的重点是要做一个简单的串口通讯程序。
工欲善其事必先利其器 , 那么接下来干活来了 , 想编程得有趁手的工具 , 所需工具如下 :
1. Virtual Serial Port Driver 用来创建虚拟的串口 , 此工具的使用请自行百度,很简单
2. 串口调试助手 , 用来辅助调试程序 , 此工具的使用也请自行百度 , so easy
3. RXTX 串口编程利器 , 官方还是很可以的 , 下载包中有操作文档说明 , 需要注意的是下载时要匹配自己的电脑系统,区分32bit 和 64bit的
接下来要快速上手 , 不搞概念什么的
1. 将RXTX下载包中的 RXTXcomm.jar 添加到项目中可以让java类使用
2. 给你提供一个带注释的串口工具类
import gnu.io.CommPort; import gnu.io.CommPortIdentifier; import gnu.io.SerialPort; import gnu.io.SerialPortEventListener; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Enumeration; public class SerialPortUtil { private static SerialPortUtil serialPortUtil = null; static{ // 在该类被classLoader加载时就初始化一个SerialPortUtil对象 if(serialPortUtil == null){ serialPortUtil = new SerialPortUtil(); } } private SerialPortUtil(){ } public static SerialPortUtil getInstance(){ if(serialPortUtil == null){ serialPortUtil = new SerialPortUtil(); } return serialPortUtil; } /** * 查找可用的串口 * @return 可用串口的名称列表 */ public static final ArrayList<String> findPort(){ Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers(); ArrayList<String> result = new ArrayList<>(); while (portList.hasMoreElements()){ String portName = portList.nextElement().getName(); result.add(portName); } return result; } /** * 打开端口 * @param portName 端口名称 * @param baudRate 波特率 * @param dataBits 数据位 * @param parity 检验位(奇偶位) * @param stopBits 停止位 * @return 串口对象 */ public static final SerialPort openPort(String portName,Integer baudRate,Integer dataBits,Integer parity,Integer stopBits){ try{ // 通过端口名称识别端口 CommPortIdentifier commPortIdentifier = CommPortIdentifier.getPortIdentifier(portName); // 打开端口 , 并给端口名称和一个超时时间 CommPort commPort = commPortIdentifier.open(portName,2000); // 判断是不是串口 if(commPort instanceof SerialPort){ SerialPort serialPort = (SerialPort)commPort; serialPort.setSerialPortParams(baudRate,dataBits,stopBits,parity); return serialPort; }else{ return null; } }catch (Exception e){ e.printStackTrace(); } return null; } /** * 关闭串口 * @param serialPort 串口对象 */ public static void closePort(SerialPort serialPort){ if(serialPort !=null){ serialPort.close(); serialPort = null; } } /** * 给串口发送数据 * @param serialPort 串口对象 * @param data 待发送的数据 */ public static void sendToPort(SerialPort serialPort,byte[] data){ OutputStream os = null; try{ os = serialPort.getOutputStream(); os.write(data); os.flush(); }catch (Exception e){ e.printStackTrace(); }finally{ try{ if(os !=null){ os.close(); os = null; } }catch (IOException e){ e.printStackTrace(); } } } /** * 从串口读取数据 * @param serialPort 当前已经建立连接的SerialPort对象 * @return 读取到的数据 */ public static byte[] readFromPort(SerialPort serialPort){ InputStream is = null; byte[] result = null; try{ is = serialPort.getInputStream(); int bufferLength = is.available(); while (bufferLength != 0){ result = new byte[bufferLength]; // 初始化byte数组为buffer中数据的长度 is.read(result); bufferLength = is.available(); } }catch (Exception e){ e.printStackTrace(); }finally { try{ if(is!=null){ is.close(); is = null; } }catch (IOException e){ e.printStackTrace(); } } return result; } /** * 添加监听器 * @param serialPort 串口对象 * @param listener 串口监听器 */ public static void addListener(SerialPort serialPort, SerialPortEventListener listener){ try{ // 给串口添加监视器 serialPort.addEventListener(listener); // 设置当有数据到达时唤醒监听接收进程 serialPort.notifyOnDataAvailable(true); // 设置当通讯中断时唤醒中断线程 serialPort.notifyOnBreakInterrupt(true); }catch (Exception e){ e.printStackTrace(); } } /** * 删除监听器 * @param serialPort 串口对象 */ public static void removeListener(SerialPort serialPort){ serialPort.removeEventListener(); } }
3. 添加发送数据的测试类
import gnu.io.SerialPort;
public class RXTXtest { public static void main(String[] args) { ArrayList<String> allPorts = SerialPortUtil.findPort(); System.out.println("获取到的串口有:"); for (String portName : allPorts) { System.out.println(portName); } System.out.println("获取全部串口方法执行完成"); final SerialPort serialPort = SerialPortUtil.openPort("COM2", 9600, 8, 0, 1); String str = "hello port"; byte[] bytes = str.getBytes(); SerialPortUtil.sendToPort(serialPort, bytes); } }
4. 添加接收数据的测试类
import gnu.io.SerialPort; import gnu.io.SerialPortEvent; import gnu.io.SerialPortEventListener; public class RXTXtest1 { private static String res = null; public static void main(String[] args) { final SerialPort serialPort = SerialPortUtil.openPort("COM3", 9600, 8, 0, 1); SerialPortUtil.addListener(serialPort, new SerialPortEventListener() { @Override public void serialEvent(SerialPortEvent serialPortEvent) { if (serialPortEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) { //如果是数据通知 byte[] bytes = SerialPortUtil.readFromPort(serialPort); res = new String(bytes); System.out.println("获取到的数据长度是: " + bytes.length); System.out.println("收到的数据是: " + res); } } }); } }
5. 需要注意的是 RXTXtest1中的 COM3 和 RXTXtest中的 COM2 是通过Virtual Serial Port Driver工具虚拟出来的一对串口
6. 接下来就可以运行看效果了 , 运行RXTXtest1 , 再运行RXTXtest , 就可以去看控制台的输出了
程序所需的工具也都上传了百度网盘, 链接如下:
链接:https://pan.baidu.com/s/1G2k7_bkk6TlENI8MNlJ85Q
提取码:cf39
至此 java串口编程入门的完整体验分享结束 , 做个记录 !