串口通信原理

串口通信(Serial Communications)的概念非常简单,串口按位(bit)发送和接收字节。 尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。它很简单并且能够实现远距离通信。比如IEEE488定义并行通行状态时,规定设备线总长不得超过20米,并且任意两个设备间的长度不得超过2米;而对于串口而言,长度可达1200米。典型地,串口用于ASCII码字符的传输。通信使用3根线完成,分别是地线、发送、接收。由于串口通信是异步的,端口能够在一根线上发送数据同时在另一根线上接收数据。其他线用于握手,但不是必须的。串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。对于两个进行通信的端口,这些参数必须匹配。

windows 查询本地串口

鼠标右键此电脑点击管理菜单,点击设备管理器,找到本地COM端口,我电脑上是COM4端口


Java实现串口通信_ide

windows 环境配置RXTXcomm.jar

资源下载(win64位 )
复制rxtxParallel.dll,rxtxSerial.dll这两个文件到 JAVA_HOME\jre\bin目录下,复制RXTXcomm.jar文件到
JAVA_HOME\jre\lib\ext目录下

idea项目添加RXTXcomm.jar包

打开 File -> Project Structure


Java实现串口通信_串口_02

打开SDKs,点击+号,添加本地RXTXcomm.jar包


Java实现串口通信_ide_03

找到上面复制的RXTXcomm.jar包

Java实现串口通信_串口_04

代码示例

import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;

/**
* TODO
*
* @author linfeng
* @date 2022/4/24 14:57
*/
public class SerialPortManager {

private static String portName = "COM4"; //本地COM口
private static CommPortIdentifier commPortIdentifier;
private static SerialPort serialPort;
private static OutputStream out;
private static InputStream in;
private static int baud = 9600;

public static void main(String[] args) throws Exception {
//打开串口
commPortIdentifier = CommPortIdentifier.getPortIdentifier(portName);
serialPort = (SerialPort) commPortIdentifier.open(portName,2000);
// 注册一个SerialPortEventListener事件来监听串口事件
serialPort.addEventListener(new SerialPortListener());
// 数据可用则触发事件
serialPort.notifyOnDataAvailable(true);
// 打开输入输出流
in = serialPort.getInputStream();
// 设置串口参数,波特率9600,8位数据位,1位停止位,无奇偶校验
serialPort.setSerialPortParams(baud, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
System.out.println("打开串口成功");
}


public static class SerialPortListener implements SerialPortEventListener{
@Override
public void serialEvent(SerialPortEvent serialPortEvent){
switch (serialPortEvent.getEventType()) {
case SerialPortEvent.DATA_AVAILABLE:
//Data available at the serial port,端口有可用数据。读到缓冲数组,输出到终端
System.out.println("端口有可用数据");
try {
if (in != null) {
//缓冲区可自己修改
byte[] cache = new byte[12];
int availableBytes = 0;
availableBytes = in.available();
while (availableBytes > 0) {
in.read(cache);
String[] data = bytes2HexString(cache).split(" ");
System.out.println(bytes2HexString(cache));
}
}
}catch (Exception e) {
e.printStackTrace();
}
break;
case SerialPortEvent.BI:
//Break interrupt,通讯中断
System.out.println("通讯中断");
break;
case SerialPortEvent.OE:
//Overrun error,溢位错误
System.out.println("溢位错误");
break;
case SerialPortEvent.FE:
//Framing error,传帧错误
System.out.println("传帧错误");
break;
case SerialPortEvent.PE:
//Parity error,校验错误
System.out.println("校验错误");
break;
case SerialPortEvent.CD:
//Carrier detect,载波检测
System.out.println("载波检测");
break;
case SerialPortEvent.CTS:
//Clear to send,清除发送
System.out.println("清除发送");
break;
case SerialPortEvent.DSR:
// Data set ready,数据设备就绪
System.out.println("数据设备就绪");
break;
case SerialPortEvent.RI:
//Ring indicator,响铃指示
System.out.println("响铃指示");
break;
case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
// Output buffer is empty,输出缓冲区清空
System.err.println("监听端口出现了异常");
break;
}
}
}
/*
* 字节数组转16进制字符串
*/
public static String bytes2HexString(byte[] b){
String r = "";
for (int i = 0; i < b.length; i++) {
String hex = Integer.toHexString(b[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
r += hex.toUpperCase()+" ";
}
return r;
}

/**
* 获取系统com端口
* @return
*/
public static String getSystemSerialPort(){
Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();
String portName ="";
while (portList.hasMoreElements()) {
portName = portList.nextElement().getName();
System.out.println(portName);
}
return portName;
}
}

串口调式工具

这可以调试本地串口收发数据。

Java实现串口通信_串口_05