一、串口通信原理
串口通信(Serial Communications)的概念非常简单,串口按位(bit)发送和接收字节。 尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。它很简单并且能够实现远距离通信。比如IEEE488定义并行通行状态时,规定设备线总长不得超过20米,并且任意两个设备间的长度不得超过2米;而对于串口而言,长度可达1200米。典型地,串口用于ASCII码字符的传输。通信使用3根线完成,分别是地线、发送、接收。由于串口通信是异步的,端口能够在一根线上发送数据同时在另一根线上接收数据。其他线用于握手,但不是必须的。串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。对于两个进行通信的端口,这些参数必须匹配。
windows 查询本地串口
设备管理器,找到本地COM端口,我电脑上是COM4端口
二、准备工作
准备工作
1.下载
地址: http://fizzed.com/oss/rxtx-for-java
这里的下载是根据jdk安装的位数下载,我之前下载的是W64的版本,电脑系统也是64的,但是代码跑不起来,后来才发现我电脑的JDK是32位的。
2、下载完成后将 rxtxParallel.dll 、 rxtxSerial.dll 、文件拷贝到放入<JAVA_HOME>\jre\bin中
复制RXTXcomm.jar文件到JAVA_HOME\jre\lib\ext目录下
这一步非常重要,把rxtxParallel.dll rxtxSerial.dll这两个文件放到jdk的bin目录下面,如果你不放当你后面打包后运行打开串口会报找不到这两个文件的错误,百思不得齐解(困扰了我一个下午)
3、引入
<dependency> <groupId>com.test</groupId> <artifactId>rxtxcomm</artifactId> <version>2.2</version> <scope>system</scope> <systemPath>${basedir}/lib/RXTXcomm.jar</systemPath> </dependency>
<dependency> <groupId>org.bidib.jbidib.org.qbang.rxtx</groupId> <artifactId>rxtxcomm</artifactId> <version>2.2</version> </dependency>方式2
<dependency> <groupId>org.bidib.jbidib.org.qbang.rxtx</groupId> <artifactId>rxtxcomm</artifactId> <version>2.2</version> </dependency>引入
三、代码实现串口通信
1、串口工具类
1
2 public class SerialPortUtil {
3 /**
4 * 获得系统可用的端口名称列表(COM0、COM1、COM2等等)
5 *
6 * @return List<String>可用端口名称列表
7 */
8
9 @SuppressWarnings("unchecked")
10 public static List<String> getSerialPortList() {
11 List<String> systemPorts = new ArrayList<>();
12 //获得系统可用的端口
13 Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();
14 while (portList.hasMoreElements()) {
15 String portName = portList.nextElement().getName();//获得端口的名字
16 systemPorts.add(portName);
17 }
18 return systemPorts;
19 }
20
21 /**
22 * 打开串口
23 *
24 * @param serialPortName 串口名称
25 * @return SerialPort 串口对象
26 * @throws NoSuchPortException 对应串口不存在
27 * @throws PortInUseException 串口在使用中
28 * @throws UnsupportedCommOperationException 不支持操作操作
29 */
30 public static SerialPort openSerialPort(String serialPortName)
31 throws NoSuchPortException, PortInUseException, UnsupportedCommOperationException {
32 SerialPortParameter parameter = new SerialPortParameter(serialPortName);
33 return openSerialPort(parameter);
34 }
35
36 /**
37 * 打开串口
38 *
39 * @param serialPortName 串口名称
40 * @param baudRate 波特率
41 * @return SerialPort 串口对象
42 * @throws NoSuchPortException 对应串口不存在
43 * @throws PortInUseException 串口在使用中
44 * @throws UnsupportedCommOperationException 不支持操作操作
45 */
46 public static SerialPort openSerialPort(String serialPortName, int baudRate)
47 throws NoSuchPortException, PortInUseException, UnsupportedCommOperationException {
48 SerialPortParameter parameter = new SerialPortParameter(serialPortName, baudRate);
49 return openSerialPort(parameter);
50 }
51
52 /**
53 * 打开串口
54 *
55 * @param serialPortName 串口名称
56 * @param baudRate 波特率
57 * @param timeout 串口打开超时时间
58 * @return SerialPort 串口对象
59 * @throws NoSuchPortException 对应串口不存在
60 * @throws PortInUseException 串口在使用中
61 * @throws UnsupportedCommOperationException 不支持操作操作
62 */
63 public static SerialPort openSerialPort(String serialPortName, int baudRate, int timeout)
64 throws NoSuchPortException, PortInUseException, UnsupportedCommOperationException {
65 SerialPortParameter parameter = new SerialPortParameter(serialPortName, baudRate);
66 return openSerialPort(parameter, timeout);
67 }
68
69 /**
70 * 打开串口
71 *
72 * @param parameter 串口参数
73 * @return SerialPort 串口对象
74 * @throws NoSuchPortException 对应串口不存在
75 * @throws PortInUseException 串口在使用中
76 * @throws UnsupportedCommOperationException 不支持操作操作
77 */
78 public static SerialPort openSerialPort(SerialPortParameter parameter)
79 throws NoSuchPortException, PortInUseException, UnsupportedCommOperationException {
80 return openSerialPort(parameter, 2000);
81 }
82
83 /**
84 * 打开串口
85 *
86 * @param parameter 串口参数
87 * @param timeout 串口打开超时时间
88 * @return SerialPort串口对象
89 * @throws NoSuchPortException 对应串口不存在
90 * @throws PortInUseException 串口在使用中
91 * @throws UnsupportedCommOperationException 不支持操作操作
92 */
93 public static SerialPort openSerialPort(SerialPortParameter parameter, int timeout)
94 throws NoSuchPortException, PortInUseException, UnsupportedCommOperationException {
95 //通过端口名称得到端口
96 CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(parameter.getSerialPortName());
97 //打开端口,(自定义名字,打开超时时间)
98 CommPort commPort = portIdentifier.open(parameter.getSerialPortName(), timeout);
99 //判断是不是串口
100 if (commPort instanceof SerialPort) {
101 SerialPort serialPort = (SerialPort) commPort;
102 //设置串口参数(波特率,数据位8,停止位1,校验位无)
103 serialPort.setSerialPortParams(parameter.getBaudRate(), parameter.getDataBits(), parameter.getStopBits(), parameter.getParity());
104 System.out.println("开启串口成功,串口名称:" + parameter.getSerialPortName());
105 return serialPort;
106 } else {
107 //是其他类型的端口
108 throw new NoSuchPortException();
109 }
110 }
111
112
113 /**
114 * 关闭串口
115 *
116 * @param serialPort 要关闭的串口对象
117 */
118 public static void closeSerialPort(SerialPort serialPort) {
119 serialPort.close();
120 System.out.println("关闭了串口:" + serialPort.getName());
121
122 }
123
124 /**
125 * 向串口发送数据
126 *
127 * @param serialPort 串口对象
128 * @param data 发送的数据
129 */
130 public static void sendData(SerialPort serialPort, byte[] data) {
131 OutputStream os = null;
132 try {
133 //获得串口的输出流
134 os = serialPort.getOutputStream();
135 os.write(data);
136 os.flush();
137 } catch (IOException e) {
138 e.printStackTrace();
139 } finally {
140 try {
141 if (os != null) {
142 os.close();
143 }
144 } catch (IOException e) {
145 e.printStackTrace();
146 }
147 }
148 }
149
150 /**
151 * 从串口读取数据
152 *
153 * @param serialPort 要读取的串口
154 * @return 读取的数据
155 */
156 public static byte[] readData(SerialPort serialPort) {
157 InputStream is = null;
158 byte[] bytes = null;
159 try {
160 //获得串口的输入流
161 is = serialPort.getInputStream();
162 //获得数据长度
163 int bufflenth = is.available();
164 while (bufflenth != 0) {
165 //初始化byte数组
166 bytes = new byte[bufflenth];
167 is.read(bytes);
168 bufflenth = is.available();
169 }
170 } catch (IOException e) {
171 e.printStackTrace();
172 } finally {
173 try {
174 if (is != null) {
175 is.close();
176 }
177 } catch (IOException e) {
178 e.printStackTrace();
179 }
180 }
181 return bytes;
182 }
183
184 /**
185 * 给串口设置监听
186 *
187 * @param serialPort serialPort 要读取的串口
188 * @param listener SerialPortEventListener监听对象
189 * @throws TooManyListenersException 监听对象太多
190 */
191 public static void setListenerToSerialPort(SerialPort serialPort, SerialPortEventListener listener) throws TooManyListenersException {
192 //给串口添加事件监听
193 serialPort.addEventListener(listener);
194 //串口有数据监听
195 serialPort.notifyOnDataAvailable(true);
196 //中断事件监听
197 serialPort.notifyOnBreakInterrupt(true);
198 }
199 }
2、初始化串口,以及监听串口发送过来的数据,然后监听到一条就保存一条到数据库中去
1 private SerialPort serialPort; 2 /** 3 * 初始化串口 4 * 5 * @throws IOException 6 */ 7 @SuppressWarnings("unchecked") 8 public void initDriverSerialPort() { 9 SqlSession session = MybatisUtils.getSession(); 10 SerialPortMapper mapper = session.getMapper(SerialPortMapper.class); 11 rfid_print.setDisable(false); 12 13 try { 14 //打开串口,然后获取所有串口的一个集合,然后通过获取文本框里面的内容来选择串口 15 serialPort = SerialPortUtil.openSerialPort(port_comboBox.getValue()); 16 if (serialPort !=null){ 17 new Alert(Alert.AlertType.NONE, "打开端口成功", new ButtonType[]{ButtonType.CLOSE}).show(); 18 }else { 19 new Alert(Alert.AlertType.NONE, "未找到该端口,打开失败", new ButtonType[]{ButtonType.CLOSE}).show(); 20 } 21 // 启动一个线程发送10次6463 22 new Thread(() -> { 23 String s = "6463"; 24 byte[] bytes = s.getBytes(); 25 SerialPortUtil.sendData(serialPort, bytes);//发送数据 26 try { 27 Thread.sleep(1000); 28 } catch (InterruptedException e) { 29 e.printStackTrace(); 30 } 31 }).start(); 32 //设置串口的listener 33 SerialPortUtil.setListenerToSerialPort(serialPort, event -> { 34 //数据通知 35 if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) { 36 byte[] bytes = SerialPortUtil.readData(serialPort); 37 System.out.println("收到的数据长度:{}" + bytes.length); 38 String s = new String(bytes); 39 String[] split = s.split(","); 40 Serialport1 serialport1=new Serialport1(); 41 serialport1.setCarCode(split[0]); 42 serialport1.setTime(split[1]); 43 serialport1.setYup(split[2]); 44 serialport1.setYdown(split[3]); 45 serialport1.setYtest(split[4]); 46 serialport1.setZup(split[5]); 47 serialport1.setZdown(split[6]); 48 serialport1.setZtest(split[7]); 49 serialport1.setLightOnUp(split[8]); 50 serialport1.setLightUpDown(split[9]); 51 serialport1.setLightOnTest(split[10]); 52 serialport1.setStatus(split[11]); 53 int i = mapper.setSerialport(serialport1); 54 System.out.println("成功插入"+i+"条数据!!!"); 55 session.commit(); //提交事务,重点!不写的话不会提交到数据库 56 session.close(); 57 58 } 59 60 }); 61 } catch (NoSuchPortException | PortInUseException | UnsupportedCommOperationException | TooManyListenersException e) { 62 e.printStackTrace(); 63 } 64 }
3、关闭串口
/** * 关闭串口 * * @throws IOException */ public void closeDriverSerialPort() { SerialPortUtil.closeSerialPort(serialPort); new Alert(Alert.AlertType.NONE, "关闭端口成功", new ButtonType[]{ButtonType.CLOSE}).show(); }
4、如果连接成功控制台就会打印消息,打开串口成功,关闭串口com2
测试工具
虚拟串口工具 Configure Virtual Serial Port Driver
串口通信工具 友善串口调试助手