Ubuntu下图形界面串口工具CuteCom的安装和升级

串口的图形界面化工具在Windows下很多, 但是在Linux下可选择的就很少, CuteCom 是相对比较好用的一款了. Ubuntu20.04默认安装的是0.30.3, 这是一个比较早的版本, 最新的版本是0.51.0, 如果需要自定义RTS电平高低, 例如连接W801这样RESET连接了RTS的开发板, 就需要升级到最新版.

安装和更新到最新版本

默认安装

在Ubuntu下使用apt可以直接安装

sudo apt install cutecom

这样安装的是0.30.3版本

CuteCom的项目地址

如果需要使用最新版本, 需要自行编译

现在最新的代码在Gitlab, 当前版本为0.51.0

环境准备

CuteCom并未提供预编译的安装包, 所以需要自己本地编译, 本地编译需要安装Qt的开发环境

apt install apt-transport-https git dh-make build-essential autoconf autotools-dev qt5-default libssl-dev qt5keychain-dev devscripts

因为CuteCom用到了Qtserial, 所以还需要安装

apt install libqt5serialport5-dev

下载和编译

git clone https://gitlab.com/cutecom/cutecom.git
cd cuteCom
cmake .
make

编译完成后在同一目录下, 可以看到cutecom的可执行文件

替换本机安装的CuteCom

# 确认cutecom的位置
whereis cutecom
# 本例是在/usr/bin
cd /usr/bin
mv cutecom cutecom.0.30.3
mv ~/cutecom/cutecom .

对于使用Qt Creator的用户, 在cmake之前, Qt Creator不能直接编译Cutecom项目, 在cmake之后, Qt Creator就可以在IDE里直接编译了.

新版本中的RTS控制功能

在设置中, 如果选择了Flow Control为NONE, 在面板上会增加两个勾选框选项: RTS和DTR. 使用中, 勾选RTS会拉低电平, 不勾选则会使RTS保持低电平, 在连接W801开发板时, 需要取消勾选. 如果在W801开发板上已经给RESET和GND之间加焊了电容, 可以在开发板运行中打开和关闭串口而不会导致开发板重启.

在连接状态中, 可以通过勾选/取消勾选实时控制RTS的电平状态.

Cutecom的代码解读

CuteCom的是比较标准的Qt项目

项目文件 CuteCom.pro

项目文件中定义了项目包含的.cpp, .h文件, .ui后缀的界面文件, 资源文件resources.qrc
DISTFILES设置的是qt.astylerc, 这个似乎是代码格式插件Artistic Style的配置

启动入口 main.cpp

这里设置程序名称, 可以看到已经使用了QCoreApplication::translate(, 可以支持多国化, 但是现在还没有其它语言的资源
然后就是初始化MainWindow, show()启动

主窗口 mainwindow.cpp 和 mainwindow.h

  • 主界面在mainwidnow.ui中定义, 最外层使用的是QMainWindow控件
  • 主界面上需要包含的元素, 其它的界面元素类, 在mainwindow.h中声明, 在mainwindow.cpp中创建并加入到对应的QWidget中
  • mainwindow.cpp 通过 mainwindows.h 关联ui ui_mainwindow.h
  • ui_mainwindow.h 是由ui文件生成的, 其中不仅声明了界面元素, 还定义了 setupUi() 方法, 里面有具体的界面展示实现, 以及 retranslateUi() 方法, 用于对界面元素的多国化展示
    • setupUi() 在 mainwindow.cpp 的构建方法中调用.
MainWindow::MainWindow(QWidget *parent, const QString &session)
    : QMainWindow(parent)
    , m_device(new QSerialPort(this))
    , m_deviceState(DEVICE_CLOSED)
    , m_progress(nullptr)
    , m_sz(nullptr)
    , m_previousChar('\0')
    , m_command_history_model(nullptr)
    , m_ctrlCharactersPopup(nullptr)
    , m_keyRepeatTimer(this)
    , m_keyCode('\0')
    , m_cmdBufIndex(0)
    , m_reconnectTimer(this)
{
    QCoreApplication::setOrganizationName(QStringLiteral("CuteCom"));
    // setting it to CuteCom5 will prevent the original CuteCom's settings file
    // to be overwritten
    QCoreApplication::setApplicationName(QStringLiteral("CuteCom5"));
    QCoreApplication::setApplicationVersion(QStringLiteral("%1").arg(CuteCom_VERSION));
    //    qRegisterMetaType<Settings::LineTerminator>();

    setupUi(this);

    m_bt_sendfile->setEnabled(false);
    m_command_history->setEnabled(false);
    m_command_history->setSelectionMode(QAbstractItemView::SelectionMode::ExtendedSelection);

    m_lb_logfile->setStyleSheet(" QLabel:hover{color: blue;} ");
    ...
  • retranslateUi() 方法未被调用
  • 在 qmainwindow.h 中, 使用QT_CONFIG()宏定义根据编译环境的Qt是否包含某个特性而加入对应的声明, 不需要开发者关心
/*
    The QT_CONFIG macro implements a safe compile time check for features of Qt.
    Features can be in three states:
        0 or undefined: This will lead to a compile error when testing for it
        -1: The feature is not available
        1: The feature is available
*/
#define QT_CONFIG(feature) (1/QT_FEATURE_##feature == 1)
  • 加入ControlPanel
controlPanel = new ControlPanel(this->centralWidget(), m_settings);
  • 加入状态栏的方式和ControlPanel的方式不一样
// setup status bar with initial infromation
m_device_statusbar = new StatusBar(this);
m_device_statusbar->sessionChanged(m_settings->getCurrentSession());
this->statusBar()->addWidget(m_device_statusbar);

mainwindow 中的用户动作, 一部分是通过 connect() 实现关联, 另一部分是通过 eventFilter(), 通过控件的 installEventFilter() 方法, 将 eventFilter() 中定义的逻辑关联到当前控件上.

mainwindow 中, 使用 signal 关联 controlpanl 传递来的连接/关闭串口的操作, 调用当前类下的连接/关闭方法

connect(controlPanel, &ControlPanel::openDeviceClicked, this, &MainWindow::openDevice);
connect(controlPanel, &ControlPanel::closeDeviceClicked, this, &MainWindow::closeDevice);

对RTS和DTR的控制

  • 处理方法为void MainWindow::setRTSLineState(int checked), 这个方法里面的m_device就是一个QSerialPort设备, 对应的setRequestToSend(true)方法会将RTS电平拉低(有些硬件的电平是相反的)
void MainWindow::setRTSLineState(int checked)
{
    if ((nullptr != m_device) && (true == m_device->isOpen())) {
        if (Qt::CheckState::Checked == static_cast<Qt::CheckState>(checked)) {
            m_device->setRequestToSend(true);
        } else {
            m_device->setRequestToSend(false);
        }
    }
}
  • 消息绑定在mainwindow.cpp里, connect(controlPanel->m_rts_line, &QCheckBox::stateChanged, this, &MainWindow::setRTSLineState);

Settings控制面板的收起和打开

  • 信号关联connect(m_panel_settings, &QTabWidget::tabBarClicked, this, &ControlPanel::tabClicked);
  • 对应的tabClicked是在controlpanel.h中定义的
// slots
void tabClicked(int i)
{
    Q_UNUSED(i);
    toggleMenu();
}
  • toogleMenu()方法里实现了控制面板的收起和打开
void ControlPanel::toggleMenu()
{
    // Create animation
    QPropertyAnimation *animation = new QPropertyAnimation(this, "pos");
    QPoint endPos = m_menuVisible ? QPoint(m_x, m_y) : QPoint(m_x, -13);
    //    qDebug() << m_menuVisible << endPos;
    animation->setStartValue(pos());
    animation->setEndValue(endPos);
    animation->start();
    if (m_menuVisible) {
        m_panel_settings->setTabIcon(0, showIcon);
        m_menuVisible = false;
    } else {
        m_panel_settings->setTabIcon(0, hideIcon);
        m_menuVisible = true;
        m_combo_Baud->setFocus();
    }
}

问题

如果使用Ubuntu20.04自带的qt库(5.12.x版本)编译, 控制面板界面的那些输入和下拉控件高度在HDPI屏幕下会特别小, 如果使用Qt Creator的qt库(5.14.x版本)编译, 这个高度就是正常的.

原文地址:https://www.cnblogs.com/milton/p/15631160.html