QT(14)-UBUNTU下QT使用串口

1.环境配置

复制代码
sudo apt-get install build-essential
sudo apt-get install cmake qt5-default qtcreator
sudo apt-get install libqt5serialport5
sudo apt-get install libqt5serialport5-dev
sudo apt remove brltty

2.安装CH340驱动

复制代码
cd /lib/modules/$(uname -r)/kernel/drivers/usb/serial
sudo rm -rf ch341.ko

下载
http://www.wch.cn/download/CH341SER_LINUX_ZIP.html
解压
复制代码
uname -r
打开
https://elixir.bootlin.com/linux/v5.8/source/drivers/usb/serial/ch341.c
替换源码

make
sudo cp ch341.ko /lib/modules/$(uname -r)/kernel/drivers/usb/serial
cd /lib/modules/$(uname -r)/kernel/drivers/usb/serial

测试
sudo apt install cutecom
sudo cutecom

插拔USB执行dmesg会显示连接信息

3.QT源码

复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    customplot_init();
    serial_init();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::customplot_init()
{
    ui->customplot->clearGraphs();
    ui->customplot->addGraph();
    ui->customplot->graph(0)->setName("波形显示");

    //坐标轴使用时间刻度
    QSharedPointer<QCPAxisTickerTime> timeTicker(new QCPAxisTickerTime);
    timeTicker->setTimeFormat("%h:%m:%s");
    ui->customplot->xAxis->setTicker(timeTicker);
    ui->customplot->xAxis->setLabel("时间");//("时间(T)");
    ui->customplot->yAxis->setLabel("电压(V)");
    ui->customplot->legend->setVisible(true);
    //设置基本坐标轴(左侧Y轴和下方X轴)可拖动、可缩放、曲线可选、legend可选、设置伸缩比例,使所有图例可见
    ui->customplot->setInteractions(QCP::iRangeDrag|QCP::iRangeZoom| QCP::iSelectAxes |
                                      QCP::iSelectLegend | QCP::iSelectPlottables);
}

void MainWindow::serial_init()
{
    //读取串口信息
    foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
    {
        // 自动读取串口号添加到端口portBox中
        QSerialPort serial;
        serial.setPort(info);
        if(serial.open(QIODevice::ReadWrite))
        {
            ui->portBox->addItem(info.portName());
            serial.close();
        }
    }
    QStringList baudList;   //波特率
    QStringList parityList; //校验位
    QStringList dataBitsList;   //数据位
    QStringList stopBitsList;   //停止位
    // 波特率    //波特率默认选择下拉第三项:9600
    baudList<<"1200"<<"2400"<<"4800"<<"9600"
           <<"14400"<<"19200"<<"38400"<<"56000"
          <<"57600"<<"115200";
    ui->rateBox->addItems(baudList);
    ui->rateBox->setCurrentIndex(3);
    // 校验      //校验默认选择无
    parityList<<"无"<<"奇"<<"偶";
    ui->checkBox->addItems(parityList);
    ui->checkBox->setCurrentIndex(0);
    // 数据位      //数据位默认选择8位
    dataBitsList<<"5"<<"6"<<"7"<<"8";
    ui->dataBox->addItems(dataBitsList);
    ui->dataBox->setCurrentIndex(3);
    // 停止位      //停止位默认选择1位
    stopBitsList<<"1"<<"2";
    ui->stopBox->addItems(stopBitsList);
    ui->stopBox->setCurrentIndex(0);
}

void MainWindow::on_searchBtn_clicked()
{
    ui->portBox->clear();
    //通过QSerialPortInfo查找可用串口
    foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
    {   //在portBox中显示可用串口
        ui->portBox->addItem(info.portName());
    }
}


void MainWindow::on_openBtn_clicked()
{
    // 打开串口
    if(ui->openBtn->text() == "打开串口")
    {
        SerialPort = new QSerialPort;
        // 设置串口号
        SerialPort->setPortName(ui->portBox->currentText());
        // 打开串口
        if(SerialPort->open(QIODevice::ReadWrite))
        {
            // 设置波特率
            SerialPort->setBaudRate(ui->rateBox->currentText().toInt());
            //设置数据位数
            switch(ui->dataBox->currentIndex())
            {
            case 5: SerialPort->setDataBits(QSerialPort::Data5); break;
            case 6: SerialPort->setDataBits(QSerialPort::Data6); break;
            case 7: SerialPort->setDataBits(QSerialPort::Data7); break;
            case 8: SerialPort->setDataBits(QSerialPort::Data8); break;
            default: break;
            }
            // 设置校验位
            //SerialPort->setParity(QSerialPort::NoParity);
            //设置奇偶校验
            switch(ui->checkBox->currentIndex())
            {
            case 0: SerialPort->setParity(QSerialPort::NoParity); break;
            case 1: SerialPort->setParity(QSerialPort::OddParity); break;
            case 2: SerialPort->setParity(QSerialPort::EvenParity); break;
            default: break;
            }
            // 设置流控制
            SerialPort->setFlowControl(QSerialPort::NoFlowControl);
            //设置停止位
            switch(ui->stopBox->currentIndex())
            {
            case 1: SerialPort->setStopBits(QSerialPort::OneStop); break;
            case 2: SerialPort->setStopBits(QSerialPort::TwoStop); break;
            default: break;
            }
        }
        //打开串口
        else
        {
            QMessageBox::about(NULL, "提示", "串口无法打开\r\n不存在或已被占用");
            return;
        }
        ui->openBtn->setText("关闭串口");
        //下拉菜单控件使能
        ui->portBox->setEnabled(false);
        ui->rateBox->setEnabled(false);
        ui->dataBox->setEnabled(false);
        ui->checkBox->setEnabled(false);
        ui->stopBox->setEnabled(false);
        //搜索串口按键使能
        ui->searchBtn->setEnabled(false);
        //发送按键使能
        ui->sendBox->setEnabled(true);

        connect(SerialPort,&QSerialPort::readyRead,this,&MainWindow::serial_Read);      // 接收数据
    }
    // 关闭串口
    else
    {
        SerialPort->close();
        ui->openBtn->setText("打开串口");
        //下拉按键使能
        ui->portBox->setEnabled(true);
        ui->rateBox->setEnabled(true);
        ui->dataBox->setEnabled(true);
        ui->checkBox->setEnabled(true);
        ui->stopBox->setEnabled(true);
        //搜索串口按键使能
        ui->searchBtn->setEnabled(true);
        //发送按键使能
        ui->sendBox->setEnabled(false);
    }
}

void MainWindow::serial_Read()
{
    QString buffer_1;
    //从缓冲区中读取数据
    QByteArray buffer = SerialPort->readAll();
    if(!buffer.isEmpty())//如果非空说明有数据接收
    {   //转换成16进制大写
        QString str=buffer.toHex().data();
        str=str.toUpper();
        //一个16进制占4位,8位为一字节,所以每两位16进制空一格
        for(int i=0;i<str.length();i+=2)
        {
               QString str_1 = str.mid (i,2);
               buffer_1 += str_1;
               buffer_1 += " ";
        }
    //读取之前显示数据
    QString receive = ui->receiveData->toPlainText();
    //清空显示
    ui->receiveData->clear();
    //重新显示
    if(ui->radioButton_3->isChecked()==0){
            receive += QString(buffer);
            ui->receiveData->append(receive);
            }//直接显示
    else    {
            receive += QString(buffer_1);
            ui->receiveData->append(receive);
            }//16进制显示
    }
    buffer.clear();
}


void MainWindow::on_sendBox_clicked()
{
    QByteArray Data_1;
    //获取输入窗口sendData的数据
    QString Data = ui->sendData->toPlainText();
    if(ui->radioButton->isChecked())       {Data+='\r';Data+='\n';}//插入换行
    if(ui->radioButton_2->isChecked()==0)    Data_1 = Data.toUtf8();//转换成utf8格式的字节流发送
    else        Data_1 = QByteArray::fromHex (Data.toLatin1().data());//按十六进制编码发送
    // 写入发送缓存区
    SerialPort->write(Data_1);

}


void MainWindow::on_pushButton_5_clicked()
{
    ui->receiveData->clear();
}


void MainWindow::on_pushButton_4_clicked()
{
    ui->sendData->clear();
}

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#pragma execution_character_set("utf-8")

#include <QMainWindow>
#include <QObject>
#include "qcustomplot.h"
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    void customplot_init();
    void serial_init();

private slots:
    void serial_Read();//串口数据读取显示
    void on_searchBtn_clicked();
    void on_openBtn_clicked();
    void on_pushButton_5_clicked();
    void on_pushButton_4_clicked();
    void on_sendBox_clicked();

private:
    Ui::MainWindow *ui;
    QSerialPort *SerialPort;

};
#endif // MAINWINDOW_H

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport serialport

CONFIG += c++17
RC_ICONS = favicon.ico

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    QCustomPlot/qcustomplot.cpp \
    main.cpp \
    mainwindow.cpp

HEADERS += \
    QCustomPlot/qcustomplot.h \
    mainwindow.h

FORMS += \
    mainwindow.ui

INCLUDEPATH += QCustomPlot

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
相关推荐
超级架构师1 小时前
PRAXO-CORE 2.5.0:用 conformance 和显式边界构建 Go Agent 框架
开发语言·人工智能·后端·golang·ai编程·智能体框架·praxo-core
叼烟扛炮1 小时前
Linux 学习笔记(四十三):网络编程进阶——自定义协议解决 TCP 粘包与守护进程
linux·开发语言·网络·笔记·tcp/ip
LMT流氓兔2 小时前
第五单元——第十六课:给书店助手加上网页界面
java·开发语言·jvm·人工智能·oracle·langchain·1024程序员节
专注仿真2 小时前
梯度提升类(XFBoost)算法详解与代码实例
开发语言·人工智能·python·算法·大模型训练·控制算法
外收内放2 小时前
Python基础语法练习题(75)
开发语言·python·学习
sycmancia3 小时前
Qml——Image和AnimatedImage使用
qt
starzy19903 小时前
Scala循环与判断:一切皆表达式的控制流
开发语言·人工智能·scala
如若1233 小时前
Windows SSH + Headscale/Tailscale 组网及免密登录完整配置教程
运维·windows·ubuntu·ssh·内网穿透
starzy19904 小时前
Scala类和对象:从构造器到样例类的完整指南
开发语言·后端·scala
niucloud-admin4 小时前
NIUCLOUD PHP SAAS上门家政使用文档--服务订单:订单列表
开发语言·php