原创 使用QT做串口通信上位机

2023-3-29 12:01 2421 12 11 分类: MCU/ 嵌入式 文集: QT学习

以前使用VB做串口上位机,现在试用QT来做,顺便学习一下,入个门。看看有多大区别。

QT上编程用的是C++,所以Class(类)的概念(公有、私有、继承、多态、构造、析构、重载这些名词)一定要搞明白。 QT专有的信号和槽的概念。

开发用的是开源的QT Creator,具体下载,安装方法可以上B站看看大牛们的讲解。界面和使用方法,新建一个工程的方法,同样也可以看B站。

 

串口编程在VB中使用comm控件。在现在的这个QT版本中没有这个comm控件。不过可以使用两个类来完成同样的工作。

  1. #include <QtSerialPort/QSerialPort>
  2. #include <QtSerialPort/QSerialPortInfo>

MainWindow 的类定义中,私有成员增加QSerialPort *serial;

  1. class MainWindow : public QMainWindow
  2. {
  3. Q_OBJECT
  4. public:
  5. MainWindow(QWidget *parent = nullptr);
  6. ~MainWindow();
  7. private slots:
  8. void on_pbConnect_clicked();
  9. void readData();
  10. private:
  11. Ui::MainWindow *ui;
  12. QSerialPort *serial; // 私有QSerialPort成员
  13. };

 记得一定要在MainWindow的构造函数中对serial进行实例化。也就是需要让serial指向的一个实体,用于操作。

serial = new QSerialPort;      //new的作用相当于malloc,分配一个实体QSerialPort需要的内存。

严格的说,在析构函数中应该 delete serial; 以释放内存。

第一次编程时,没有实例化serial,空指针操作serial,结果程序一运行就崩溃退出。 

MainWindow::MainWindow(QWidget *parent)

    : QMainWindow(parent)

    , ui(new Ui::MainWindow)

{

    ui->setupUi(this);

    const auto infos = QSerialPortInfo::availablePorts();

    for(const QSerialPortInfo &info : infos){

        ui->cbCom->addItem(info.portName());

    }

    serial = new QSerialPort;  //实例化 serial

    connect(serial, &QSerialPort::readyRead, this, &MainWindow::readData);

}

 

在连接用的按键点击可以打开或关闭串口了。方法是判断按键上的文字。神奇的是,经常用的strcmp不存在,不过可以这样用:

if(ui->pbConnect->text() == QString("连接")) 直接判断字符串相等,不比strcmp香么?判断字符串相等肯定还是得一个字节一个字节比较。我想这个QString类一定把 “ == ”  做了重载(新定义了 == 作为字符串比较的运算符)。

 

void MainWindow::on_pbConnect_clicked()

{

    if(ui->pbConnect->text()==QString("连接")){

        serial->setPortName(ui->cbCom->currentText());

        serial->setBaudRate(QSerialPort::Baud115200);

        serial->setDataBits(QSerialPort::Data8);

        serial->setStopBits(QSerialPort::OneStop);

        serial->setParity(QSerialPort::NoParity);

        if(!serial->open(QIODevice::ReadWrite)){

            QMessageBox::information(this,"错误提示","不能打开串口",QMessageBox::Ok);

        }

        else{

            ui->cbCom->setEnabled(false);

            ui->pbConnect->setText("关闭");

        }

    }

    else{

        serial->close();

        ui->cbCom->setEnabled(true);

        ui->pbConnect->setText("连接");

    }

}

 

关于串口号的获取,在用VB时,用的是穷举法,捕获错误,非法的COM号会产生错误剔除,获得合法串口号。在QT里可以用QSerialPortInfo类,获取可用串口。这个for 循环也很有意思。不是常规的;;结构,感觉像是使用:对集合里的元素做一个遍历。可以在窗口构造函数中,或者其它地方把可用串口号送到combox里,方便选取。

    const auto infos = QSerialPortInfo::availablePorts();

    for(const QSerialPortInfo &info : infos){

        ui->cbCom->addItem(info.portName());

}

 

为了从串口获取数据,需要连接一个串口取数的槽函数。

connect(serial, &QSerialPort::readyRead, this, &MainWindow::readData); 当串口产生readyRead信号时,调用readData函数处理。而 readData,当然需要定义到private slots里面。

class MainWindow : public QMainWindow

{

    Q_OBJECT

 

public:

    MainWindow(QWidget *parent = nullptr);

    ~MainWindow();

 

private slots:

    void on_pbConnect_clicked();

    void readData();

private:

    Ui::MainWindow *ui;

    QSerialPort *serial;

};

 

每产生一次readyRead readData就被执行,程序中直接把所有接收到的内容存放到QString data里面。对于格式化数据,先前可以用sscanf读取分别放到数据或字符串里。QT里面没有sscanf感觉不爽是吧。

QStringList datlist = data.split(",",QString::SkipEmptyParts); 这个split 一下就把字符串分好了,直接使用 datlist[],就能引用。   

void MainWindow::readData()

{

    QString data = serial->readAll();

    QStringList datlist = data.split(",",QString::SkipEmptyParts);

    ui->lineEdit->setText(data);

    ui->lcdNumber1->display(datlist[0]);

    ui->lcdNumber2->display(datlist[1]);

}

 

程序运行,结果满意。效率又提升了。So easy!


好文赏现金!2023面包板社区原创奖励活动进行中:

https://mbb.eet-china.com/forum/topic/125238_1_1.html

作者: southcreek, 来源:面包板社区

链接: https://mbb.eet-china.com/blog/uid-me-408807.html

版权声明:本文为博主原创,未经本人允许,禁止转载!

PARTNER CONTENT

文章评论2条评论)

登录后参与讨论

southcreek 2023-5-9 16:50

这个得天天用。有一阵不用,又忘记了。得重新来。

southcreek 2023-3-31 16:29

项目文件中需要
QT  += serialport
不然与serial port 相关的内容不能编译
相关推荐阅读
southcreek 2024-12-04 16:32
PWM输出隔离DAC设计
这个设计的目标是产生一个隔离的DAC输出。12V供电,产生0~5V的输出。达到10000约13.3位的分辨率。要求DAC输出在改变设置后1S内能稳定。需要能长时间保持稳定和低噪声。能达到要求的DAC只...
southcreek 2024-12-04 15:23
一个基于HAL库的串口控制框架
将串口接收配置为 DMA方式,DMA 使用 DMA_CIRCULAR 模式工作。串口接收的数据实际上构成循环队列。 定义一个结构Comm_typedef 结构体中包含指向接收到的第一字节位置chrc...
southcreek 2024-07-08 11:38
接地不良导致的故障分析
这个电路的控制板需要连接显示板和识别板。5V 供电和串行控制连到显示板,显示板再连接到识别板。识别板上电位器使用一个LDO供电,将输入的5V转成3.3V。当电位器滑动时,输出电压在0~3.3V之间。...
southcreek 2024-06-26 09:15
【EMC整改】带辅助加热的滴速控制器辐射抗扰整改
这个滴速式的输液泵使用一个红外线发射和接收装置,当有液滴通过时,会扰动检测信号,识别这个扰动检测到液滴滴下,获得滴壶中的液滴速度,调整阀门大小,实现输液速度控制。控制器还配备一根加热条,用于输液时对药...
southcreek 2024-06-06 08:52
QT 使用QSettings 操作ini文件配合表格操作
这个项目可以演示 使用QSetting 读取或写入 ini文件。并使用tablewidget 显示。Ini文件的格式如下,这个文件可以事先编写。也可以在程序中生成。有一个大类,下面有一个小类使用等号设...
southcreek 2024-05-27 16:18
差分输入ADC的单端到差分转换器驱动设计
单端信号需要转换成差分信号,以便使用ADC进行转换。这个就所谓的ADC驱动电路。需要的结果为Vp = Vcm + Vi/2Vn = Vcm – Vi/2这样 Vp – Vn = Vi使用简单的加法器和...
EE直播间
更多
我要评论
2
12
关闭 站长推荐上一条 /3 下一条