开始QT编程后,由于自己本身基础较差,需要经常查询一些简单无聊的问题,有些时候好多知识点只有个印象,记不太清楚导致下不去手写代码,都需要上网搜一搜,现在记录一下自己思路或者一些常用的知识点,这样以后自己忘记了可以很快查找翻阅一下,可以当个备忘录。同时如果这些东西对其他人有帮助的话,也是特别好的,也会让自己有成就感,给自己更多的前进动力。

由于工作需要接触串口通信。在网上查了很多资料,现在做个总结。

关于串口的通信

1、串口通信需要的主要参数:波特率、校验位、数据位、停止位、控制流

2、这里,将通信参数写死,并通过定时器,实现串口自动连接,判断串口断开,发送和接收串口的信息 【后续可能会考虑使用线程来完成串口自动连接,断开判断等操作】

查看了很多CSDN上的很多关于QT串口通信的文章:文章1文章2文章3

备注:

2023/03/20 14:40懒得在修改这个文章了,后续遇到的问题都会写我的笔记进里

第一步、添加相关头文件,模块

在.pro的文件里添加模块  QT += serialport
在.cpp里添加串口通信头文件 
#include <QSerialPort>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>

第二步、在头文件中定义全局的对象

private:
QSerialPort* serial;//全局的串口对象
QTimer* timer;//全局的定时器对象

第三步、参数设置,在头文件中定义初始化参数的函数和参数变量名,在.cpp文件中实现函数

main()
{
    timer = new QTimer;
    timer->start(1000);
    timer->setSingleShot(false);//设置周期触发的定时器
    connect(timer,SIGNAL(timeout()),this,SLOT(setinit()));//周期性触发初始化的操作
}
void MainWindow::setinit()//设置串口初始化
{
    QSerialPortInfo com_info;
    foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) //循环遍历获得可用的串口号
    {
        if(info.serialNumber() == "")
        {
            com_info = info;
            break;
        }
    }
    serial->setPort(com_info);//将获得到得串口号设置为需要打开的串口号
    if(serial->open(QIODevice::ReadWrite))
    {
        timer->stop();//如果串口打开了,就停止定时器
        serial->setBaudRate(QSerialPort::Baud115200);//设置波特率:115200
        qDebug()<< "波特率设置:" << serial->setBaudRate(QSerialPort::Baud115200);

        serial->setParity(QSerialPort::NoParity);//设置校验位:no
        qDebug()<< "校验位设置:" << serial->setParity(QSerialPort::NoParity);

        serial->setDataBits(QSerialPort::Data8);//设置数据位:8位
        qDebug()<< "数据位设置:" << serial->setDataBits(QSerialPort::Data8);

        serial->setStopBits(QSerialPort::OneStop);//设置停止位:1位
        qDebug()<< "停止位设置:" << serial->setStopBits(QSerialPort::OneStop);

        serial->setFlowControl(QSerialPort::NoFlowControl);//设置无流控制
        qDebug()<< "流控制设置:" << serial->setFlowControl(QSerialPort::NoFlowControl);

        connect(serial,SIGNAL(readyRead()),this,SLOT(receiveMessage()),Qt::UniqueConnection);//串口连接槽函数
        // Qt::UniqueConnection  虽然我不知道为什么这样管用,但它却是修复了串口断开会重复弹窗的问题
        connect(serial,SIGNAL(error(QSerialPort::SerialPortError)),
                this,SLOT(showValidPort(QSerialPort::SerialPortError)),Qt::UniqueConnection);//判断串口连接状态
       //同上,不知道为什么,确实修复了重复提示弹窗问题
    }
    else
    {
        qDebug() << "串口没有打开";
    }
}

第四步、判断串口连接的状态

private slots:
 void showValidPort(QSerialPort::SerialPortError error);//检测串口的连接状态
void MainWindow::showValidPort(QSerialPort::SerialPortError error)//检测串口的连接状态
{
    if(error == QSerialPort::ResourceError || error == QSerialPort::PermissionError)
    {
        QMessageBox::critical(this, "警告","串口连接中断!请检查串口是否正确连接!");
        //        serial->clear();
        serial->close();
        timer->start(500);
    }
}

第五步、串口信息的发送和信息的接收(计划是可以实现中文,16进制发送和接收)//这里暂时只实现了16进制的数据发送和接收

private slots:
void receiveMessage();//接收串口通信设备发送的信息
void btn1_send();//按钮1发送数据
void MainWindow::receiveMessage()//接收从串口通信设备中接收到得信息
{
    QString buffer_1;//从缓冲区中读取数据
    QByteArray buffer = serial->readAll();
    if(!buffer.isEmpty())//如果非空说明有数据接收
    {
        QString str=buffer.toHex().data();//转换成16进制大写
        str=str.toUpper();
        for(int i=0;i<str.length();i+=2)//一个16进制占4位,8位为一字节,所以每两位16进制空一格
        {
            QString str_1 = str.mid (i,2);
            buffer_1 += str_1;
            buffer_1 += " ";
        }
    }
    qDebug() <<"接收到的信息是:"<< buffer_1;
  
    buffer.clear();
}

void MainWindow::btn1_send()//点击按钮1发送数据
{
    QByteArray Data_1;
    QString Data = "A1";
    Data_1 = QByteArray::fromHex (Data.toLatin1().data());//这里使用16进制发送数据
    serial->write(Data_1);
    qDebug() <<"发送的信息是:"<< Data;
}

第六步、实现自动刷新当前时间

private:
QTimer* timer2;//全局的定时器对象
private slots:
void timeread();//获取当前时间
main()
{
    timer2 = new QTimer;
    timer2->start(1000);
    timer2->setSingleShot(false);//设置周期触发的定时器
    connect(timer2,SIGNAL(timeout()),this,SLOT(timeread()));//周期性触发读取当前时间的操作
}
void MainWindow::timeread()//获取当前时间
{
    QDateTime tim = QDateTime::currentDateTime();
    QString datetime = tim.toString("yyyy - MM - dd  hh:mm:ss");
    ui->timelabel->setText(datetime);
}

后续遇到的问题:

参考他人的无边框窗口完成了自己的无边框窗口,但仍存在改进空间

自定义无边框窗口+标题栏

遇到了Qdebug和Qlabel显示中文文字乱码的问题(已解决)

在头文件中添加
#if defined(_MSC_VER) && (_MSC_VER >= 1600)
# pragma execution_character_set("utf-8")
#endif

2023/03/17 17:31 QByteArray, 提示 .isEmpty失败,但是头文件信息都有写,不知道问题是啥

物联沃分享整理
物联沃-IOTWORD物联网 » QT串口通信实践指南

发表评论