Linux读取串口实时数据

Linux 北斗串口 ttyVIZ0 实时读取

一、场景说明

现场硬件:北斗对时模块,挂载 Linux 串口/dev/ttyVIZ0

Java 业务代码使用 RXTX 配置串口参数:9600 8N1(9600 波特、8 数据位、1 停止位、无校验)

问题:直接cat /dev/ttyVIZ0不会实时输出,数据缓存攒满 / 遇换行才打印,表现和读取普通文件一致,无法实时抓取北斗 NMEA 报文。

原因:Linux 串口默认规范模式(cooked / 行缓冲),驱动缓存数据,收到 \r\n 才上送应用;必须切换 raw 原始模式,字节实时透传

二、Java RXTX 原始串口配置(项目源码)

java 复制代码
@EnableScheduling  // 必须加
@SpringBootApplication
public class YourApp {
    public static void main(String[] args) {
        SpringApplication.run(YourApp.class, args);
    }
}
java 复制代码
import com.fazecast.jSerialComm.SerialPort;
import com.fazecast.jSerialComm.SerialPortDataListener;
import com.fazecast.jSerialComm.SerialPortEvent;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.PreDestroy;
import java.util.ArrayList;
import java.util.List;

@Component
public class BeidouSerialManager {

    private static final String PORT_NAME = "/dev/ttyVIZ0";
    private SerialPort serialPort;
    private final List<String> beidouDataCache = new ArrayList<>(18);
    private volatile boolean connected = false;

    // ===================== 核心:每3秒自动检查连接 =====================
    @Scheduled(fixedRate = 3000)
    public void checkAndConnect() {
        if (connected) {
            return;
        }
        connect();
    }

    // ===================== 真正的连接逻辑(只在这里) =====================
    private void connect() {
        try {
            closePort(); // 先清理旧资源

            serialPort = SerialPort.getCommPort(PORT_NAME);
            if (serialPort == null || !serialPort.openPort()) {
                System.out.println("未检测到北斗设备,继续重试...");
                return;
            }

            // 你的配置 9600 8N1
            serialPort.setBaudRate(9600);
            serialPort.setNumDataBits(8);
            serialPort.setNumStopBits(1);
            serialPort.setParity(0);

            // 监听器
            serialPort.addDataListener(dataListener());
            connected = true;
            System.out.println("✅ 北斗串口已成功连接");

        } catch (Exception e) {
            connected = false;
        }
    }

    // ===================== 数据监听器 =====================
    private SerialPortDataListener dataListener() {
        return new SerialPortDataListener() {
            @Override
            public int getListeningEvents() {
                return SerialPort.LISTENING_EVENT_DATA_AVAILABLE;
            }

            @Override
            public void serialEvent(SerialPortEvent event) {
                try {
                    if (!serialPort.isOpen()) {
                        connected = false;
                        return;
                    }

                    byte[] buffer = new byte[1024];
                    int len = serialPort.readBytes(buffer, buffer.length);
                    if (len > 0) {
                        String data = new String(buffer, 0, len);
                        beidouDataCache.add(data);
                        System.out.println("收到北斗数据:" + data);
                    }
                } catch (Exception e) {
                    connected = false; // 异常=断开
                }
            }
        };
    }

    // ===================== 安全关闭 =====================
    @PreDestroy
    public void closePort() {
        try {
            if (serialPort != null && serialPort.isOpen()) {
                serialPort.closePort();
            }
        } catch (Exception ignored) {}
        connected = false;
    }

    public List<String> getBeidouDataCache() {
        return beidouDataCache;
    }
}
  1. 启动没插串口 → 完全没问题
  • 程序正常启动
  • 每 3 秒自动扫描
  • 插上立刻自动连接
  1. 中途拔掉 → 自动标记断开
  • 读取异常 → connected = false
  • 下一轮 3 秒自动重试
  1. 再次插上 → 自动恢复
  • 全程不需要人工干预
  • 不需要重启程序

参数释义:9600 8N1,工业北斗 / GPS 设备通用串口参数。

三、stty 命令与 Java 参数精准映射(核心配置)

3.1 对应配置命令(和 Java 完全等价)

bash 复制代码
# 配置串口为raw原始模式,关闭行缓冲、回显、流控,对齐Java 9600 8N1
stty -F /dev/ttyVIZ0 9600 cs8 -cstopb -parenb raw -echo -icrnl -onlcr -ixon
Java 配置项 stty 参数 说明
9600 波特率 9600 串口速率
8 数据位 cs8 character size=8bit
1 停止位 -cstopb 关闭双停止位,使用 1 停止位
无校验 (0) -parenb 关闭奇偶校验
实时无缓冲 raw 原始模式,取消行缓冲,单字节立即输出
关闭回显 -echo 禁止串口本地回显

-ixon:关闭 XON/XOFF 软件流控,北斗对时设备无需流控配置。

3.2 临时实时读取(调试用)

注意:配置完参数后,实时打印北斗报文:

bash 复制代码
# 终端前台实时打印,Ctrl+C终止
cat /dev/ttyVIZ0

raw 模式下收到 1 字节立刻输出,不再等待换行,和 Java 程序读取逻辑一致。

四、常见故障排查

  1. 找不到串口 /dev/ttyVIZ0 不存在
bash 复制代码
#查看系统识别串口
dmesg | grep tty
ls /dev/ttyVIZ0
  1. 乱码:波特率不匹配
    北斗备选波特率:115200,替换命令中 9600 重试。

五、补充:恢复串口默认规范模式

如需切回系统默认行缓冲模式:

bash 复制代码
stty -F /dev/ttyVIZ0 sane
相关推荐
薛定谔的悦10 小时前
储能 EMS 的功率策略:从一块电表到一次逆流的 200 毫秒
大数据·linux·能源·储能·bms
2601_9622184712 小时前
万象生鲜系统区块链溯源技术帮助生鲜企业搭建食品安全数字化体系
大数据·运维·微服务·云原生·架构
智塑未来12 小时前
中小公司在线文档选型:从协作入口到安全边界
运维·安全
新时代牛马13 小时前
Linux 内核入门地图:架构、源码目录与五大子系统
linux·运维·架构
智购科技无人售货机厂家13 小时前
2026自动售货机制冷系统维护指南:从散热器清洁到压缩机换油的工程实践~YH
运维·redis·物联网·缓存·架构
剑客的茶馆13 小时前
开发者,运维怎样转行FDE?
运维·ai·开发·fde
Julien200413 小时前
控制 SELinux 文件上下文
linux·运维·服务器
sulikey13 小时前
Linux Core Dump 完全指南:从原理到实战的崩溃调试手册。什么是core dump?程序报错core dumped怎么办?
linux·服务器·操作系统·调试·coredump
Lifangyun_WD13 小时前
第一次租 GPU 服务器怎么开始?镜像、SSH、数据存储和停机前要做什么
服务器·云计算·gpu算力·gpu算力租赁
众壹新能源科技13 小时前
功率预测误差考核怎么降?从气象源到上报口径的排查清单
运维·人工智能·自动化