QGC 中修改原生 Android 串口 BUG 实操

QGC 中修改原生 Android 串口 BUG 实操

一、QGC 原生 Android 串口实现的问题

原始 QGC 在 Android 平台下的串口实现,采用的是 ​Java + JNI 的方式

  • Java 层 使用 Android USB Host API 枚举并打开 USB 串口设备
  • 通过 JNI 注册 Native 方法
  • 将串口数据以回调的形式传递到 C++ / Qt 层

该实现方式适用于 ​USB 转串口设备,但在实际工程中存在明显局限:

该方案无法操作系统中已存在的普通串口设备(如 /dev/ttyS* ​ **、**​ /dev/ttyUSB* ​ **、**​ /dev/ttyACM*

在以下场景中尤为明显:

  • 工控 / 定制 Android 系统
  • 无人机遥控器内置 Android
  • 已由内核直接生成 tty 设备节点的串口
  • 需要高实时性、多串口并发的地面站应用

因此,原生 QGC 的 Android 串口方案在工程实践中存在适配不足的问题。


二、采用类 Linux 的原生 POSIX 串口方案

为解决上述问题,本次对 QGC 串口底层进行了修改,​放弃 Java / JNI 串口路径 ​,改为采用 ​类 Linux 的原生 POSIX 串口实现方式

该方案通过以下机制直接操作串口设备:

  • open():打开系统设备文件
  • termios / termios2:配置串口参数(波特率、数据位、校验位等)
  • ioctl():支持非标准波特率及底层控制
  • QSocketNotifier:将串口 fd 集成进 Qt 事件循环

核心特征如下:

直接操作系统设备文件(/dev/tty*),完全绕过 Java 层,仅在 C++ / Qt 层完成串口通信。

该实现本质上是 ​Qt Unix 平台(Linux / Android)通用的 QSerialPortPrivate实现,具备良好的稳定性与扩展性。


三、新串口实现的核心代码

新串口方案中,串口设备的打开方式如下:

cpp 复制代码
int flags = O_NOCTTY | O_NONBLOCK;

flags |= O_RDWR;   // 或 O_RDONLY / O_WRONLY

descriptor = ::open(systemLocation.toLocal8Bit().constData(), flags);

该代码直接获取串口设备的 ​文件描述符(fd) ,后续所有串口读写与事件监听均围绕该 fd 进行。


四、在 QGC 中的具体操作

为保证兼容性和可切换性,本次修改通过 宏控制 的方式,在原生 QGC 串口方案与新方案之间进行切换。

1️⃣ 在 QGCCommon.pri 中增加宏定义

cpp 复制代码
DEFINES += GENERAL_SERIAL_ENABLE

用于启用新的通用串口实现。


2️⃣ 在 main.cc 中屏蔽原有 Android JNI 串口逻辑

原生 QGC 会在启动时注册 Java 串口的 Native 方法,需在启用新方案时将其屏蔽:

cpp 复制代码
#ifndef GENERAL_SERIAL_ENABLE
    #if !defined(NO_SERIAL_LINK)
        QSerialPort::setNativeMethods();
    #endif
#endif

启用 GENERAL_SERIAL_ENABLE 后,QGC 将不再走 Java / JNI 串口路径。


3️⃣ 替换 libs​ 目录下的 qtandroidserialport

  • 删除原有 qtandroidserialport 实现
  • 替换为修改后的串口底层代码

该步骤确保 Android 平台下统一使用 ​POSIX 串口实现

链接: https://ug.link/dxp4800-d1e0/filemgr/share-download/?id=b904d94c152c4b33b34b702501a0c7f3

具体替换的文件在这里,无需关心

五、实测

远传融创中 S1/S2 遥控器地面站软件中串口截图:

QGC 实测版本: v4.1.3 、Stable_v4.4

相关推荐
一只小bit2 小时前
Qt 多媒体:快速解决音视频播放问题
前端·c++·qt·音视频·cpp·页面
程序小馆2 小时前
Qt cmake add_subdirectory 后无法使用子模块的资源(如图片、翻译文件)的解决方案
开发语言·qt
努力学习的小廉3 小时前
【QT(十)】—— 系统
开发语言·qt
誰能久伴不乏3 小时前
Qt 启动时序与事件循环:为什么监控启动不要放在构造函数里,以及 `QTimer::singleShot(0, ...)` 到底做了什么
c语言·c++·qt
少控科技3 小时前
QT高阶日记011
开发语言·qt
钱彬 (Qian Bin)11 小时前
项目实践17—全球证件智能识别系统(开发基于LabelMe标注的可视化审核接口)
qt·fastapi·全球证件识别
look ahead to20 小时前
关于PYQT qt designer的网格布局 单控件占多行的处理
开发语言·qt·pyqt
Lution Young1 天前
Qt隐式共享产生的问题
开发语言·qt
少控科技1 天前
QT进阶日记009
开发语言·qt