Java Simple Serial Connector 教程

简介

Java Simple Serial Connector (jSSC) 是一个轻量级的Java串口通信库,支持Windows、Linux、Mac OS X和Solaris等多平台。它的特点是简单易用、性能稳定,适合需要串口通信的Java应用程序开发。

主要特性

  • 跨平台支持

  • 简单API设计

  • 事件驱动模型

  • 支持波特率自定义

  • 支持数据位、停止位、校验位配置

  • 支持流控制

安装配置

Maven依赖

java 复制代码
<dependency>
    <groupId>org.scream3r</groupId>
    <artifactId>jssc</artifactId>
    <version>2.8.0</version>
</dependency>

基础用法

1. 获取串口列表

java 复制代码
import jssc.SerialPortList;

public class ListPorts {
    public static void main(String[] args) {
        String[] portNames = SerialPortList.getPortNames();
        System.out.println("可用串口:");
        for (String portName : portNames) {
            System.out.println(portName);
        }
    }
}

2. 打开和配置串口

java 复制代码
import jssc.SerialPort;
import jssc.SerialPortException;

public class OpenPort {
    public static void main(String[] args) {
        // 创建串口对象(Windows: COM1, Linux: /dev/ttyUSB0, Mac: /dev/tty.usbserial)
        SerialPort serialPort = new SerialPort("COM3");
        
        try {
            // 打开串口
            serialPort.openPort();
            
            // 配置串口参数
            serialPort.setParams(
                SerialPort.BAUDRATE_9600,    // 波特率
                SerialPort.DATABITS_8,        // 数据位
                SerialPort.STOPBITS_1,        // 停止位
                SerialPort.PARITY_NONE        // 校验位
            );
            
            System.out.println("串口打开成功!");
            
        } catch (SerialPortException e) {
            e.printStackTrace();
        }
    }
}

3. 发送数据

java 复制代码
// 发送字符串
serialPort.writeString("Hello Arduino!");

// 发送字节数组
byte[] data = {0x01, 0x02, 0x03, 0x04};
serialPort.writeBytes(data);

// 发送单个字节
serialPort.writeByte((byte)0x55);

4. 接收数据

java 复制代码
// 同步读取
byte[] buffer = serialPort.readBytes(10); // 读取10个字节
String received = serialPort.readString(); // 读取字符串

// 设置超时
serialPort.readBytes(10, 1000); // 最多等待1000毫秒

高级特性

1. 事件监听器

java 复制代码
import jssc.SerialPort;
import jssc.SerialPortEvent;
import jssc.SerialPortEventListener;
import jssc.SerialPortException;

public class SerialReader implements SerialPortEventListener {
    
    private SerialPort serialPort;
    
    public SerialReader(String portName) {
        serialPort = new SerialPort(portName);
        try {
            serialPort.openPort();
            serialPort.setParams(9600, 8, 1, 0);
            
            // 设置事件掩码(监听数据接收事件)
            serialPort.setEventsMask(SerialPort.MASK_RXCHAR);
            
            // 添加事件监听器
            serialPort.addEventListener(this);
            
        } catch (SerialPortException e) {
            e.printStackTrace();
        }
    }
    
    @Override
    public void serialEvent(SerialPortEvent event) {
        if (event.isRXCHAR() && event.getEventValue() > 0) {
            try {
                // 读取接收到的数据
                byte[] buffer = serialPort.readBytes(event.getEventValue());
                String received = new String(buffer);
                System.out.println("收到数据:" + received);
                
            } catch (SerialPortException e) {
                e.printStackTrace();
            }
        }
    }
    
    // 关闭串口
    public void close() {
        try {
            serialPort.closePort();
        } catch (SerialPortException e) {
            e.printStackTrace();
        }
    }
}

2. 流控制设置

java 复制代码
// 设置RTS/CTS流控制
serialPort.setFlowControlMode(
    SerialPort.FLOWCONTROL_RTSCTS_IN | 
    SerialPort.FLOWCONTROL_RTSCTS_OUT
);

// 设置XON/XOFF流控制
serialPort.setFlowControlMode(
    SerialPort.FLOWCONTROL_XONXOFF_IN | 
    SerialPort.FLOWCONTROL_XONXOFF_OUT
);

3. 手动控制RTS/DTR信号

java 复制代码
// 设置RTS信号
serialPort.setRTS(true);  // 高电平
serialPort.setRTS(false); // 低电平

// 设置DTR信号
serialPort.setDTR(true);  // 高电平
serialPort.setDTR(false); // 低电平

示例代码

完整示例:串口调试助手

java 复制代码
import jssc.*;
import java.util.Scanner;

public class SerialDebugger implements SerialPortEventListener {
    
    private SerialPort serialPort;
    private Scanner scanner;
    
    public SerialDebugger(String portName, int baudRate) {
        serialPort = new SerialPort(portName);
        scanner = new Scanner(System.in);
        
        try {
            // 打开串口
            serialPort.openPort();
            System.out.println("串口 " + portName + " 已打开");
            
            // 配置串口
            serialPort.setParams(
                baudRate,
                SerialPort.DATABITS_8,
                SerialPort.STOPBITS_1,
                SerialPort.PARITY_NONE
            );
            
            // 设置事件监听
            serialPort.setEventsMask(SerialPort.MASK_RXCHAR);
            serialPort.addEventListener(this);
            
            System.out.println("串口配置完成,波特率:" + baudRate);
            
            // 发送数据线程
            startSendThread();
            
        } catch (SerialPortException e) {
            e.printStackTrace();
        }
    }
    
    private void startSendThread() {
        Thread sendThread = new Thread(() -> {
            while (true) {
                System.out.print("请输入要发送的数据(输入'exit'退出):");
                String input = scanner.nextLine();
                
                if (input.equalsIgnoreCase("exit")) {
                    close();
                    break;
                }
                
                try {
                    // 发送数据
                    serialPort.writeString(input + "\r\n");
                    System.out.println("发送成功:" + input);
                } catch (SerialPortException e) {
                    System.out.println("发送失败:" + e.getMessage());
                }
            }
        });
        
        sendThread.start();
    }
    
    @Override
    public void serialEvent(SerialPortEvent event) {
        if (event.isRXCHAR() && event.getEventValue() > 0) {
            try {
                byte[] buffer = serialPort.readBytes(event.getEventValue());
                System.out.println("\n接收数据:" + new String(buffer));
                System.out.print("请输入要发送的数据(输入'exit'退出):");
            } catch (SerialPortException e) {
                e.printStackTrace();
            }
        }
    }
    
    private void close() {
        try {
            if (serialPort != null && serialPort.isOpened()) {
                serialPort.closePort();
                System.out.println("串口已关闭");
            }
            scanner.close();
        } catch (SerialPortException e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        // 显示可用串口
        String[] ports = SerialPortList.getPortNames();
        System.out.println("可用串口:");
        for (String port : ports) {
            System.out.println(port);
        }
        
        if (ports.length > 0) {
            // 使用第一个可用串口
            new SerialDebugger(ports[0], 9600);
        } else {
            System.out.println("没有找到可用串口");
        }
    }
}

常见问题

1. 找不到串口

  • Windows: 检查驱动是否正确安装,端口号是否正确(如COM3)

  • Linux: 检查用户是否有权限访问串口(需要加入dialout组)

    bash 复制代码
    sudo usermod -a -G dialout $USER
  • Mac: 检查是否安装了驱动,端口名称通常为/dev/tty.usbserial-*

2. 权限问题

在Linux/Mac上运行Java程序时,可能需要root权限:

java 复制代码
sudo java -jar yourprogram.jar

3. 数据乱码

检查波特率、数据位、停止位、校验位是否与设备匹配

4. 本地库加载失败

确保jssc的本地库文件(.dll/.so/.dylib)可以被Java访问,或者将库文件放在系统库路径中

5. 资源释放

确保在使用完串口后正确关闭:

java 复制代码
try {
    if (serialPort != null && serialPort.isOpened()) {
        serialPort.closePort();
    }
} catch (SerialPortException e) {
    e.printStackTrace();
}
相关推荐
xcs194052 小时前
Java 上位机防空警报系统开发
java·开发语言
sR916Mecz2 小时前
Linux 服务器磁盘扩容与目录迁移:rsync + bind mount 实现服务无感迁移(无需修改配置)
java·linux·服务器
youcans_2 小时前
【FOC-MBD】(20)矢量空间脉宽调制 (SVPWM)输出
stm32·单片机·嵌入式硬件·matlab·代码生成
点灯小铭2 小时前
基于单片机的全自动洗衣机控制器设计
单片机·嵌入式硬件
UAq6wn76j2 小时前
.NET源码生成器使用SyntaxTree生成代码及简化语法
java·开发语言·.net
火飞鹰2 小时前
封装MinIO为starter
java·数据库·spring boot
@atweiwei2 小时前
Go语言并发编程面试题精讲(上)
java·开发语言·面试·golang·channel
_MyFavorite_2 小时前
JAVA重点基础、进阶知识及易错点总结(36)Lombok 实战 + 阶段总结
java·开发语言