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();
}
相关推荐
小雅痞1 小时前
[Java][Leetcode middle] 167. 两数之和 II - 输入有序数组
java·算法·leetcode
CN-Dust1 小时前
【C++】输入cin例题专题
java·c++·算法
踏着七彩祥云的小丑2 小时前
嵌入式——认识电子元器件——温度开关系列
单片机·嵌入式硬件
xin_nai2 小时前
LeetCode热题100(Java)(6)矩阵
java·leetcode·矩阵
宣宣猪的小花园.2 小时前
C语言重难点全解析:内存管理到位运算
c语言·开发语言·单片机
代码AI弗森8 小时前
一文理清楚“算力申请 / 成本测算 / 并发评估”
java·服务器·数据库
Old Uncle Tom8 小时前
OpenClaw 记忆系统 -- 记忆预加载
java·数据结构·算法·agent
小小小米粒8 小时前
Collection单列集合、Map(Key - Value)双列集合,多继承实现。
java·开发语言·windows
摇滚侠9 小时前
expdp 查看帮助
java·数据库·oracle
FreakStudio9 小时前
亲测可用!可本地部署的 MicroPython 开源仿真器
python·单片机·嵌入式·面向对象·并行计算·电子diy·电子计算机