QT5串口编程----线程循环发送不成功问题

今天想写一个QT5的串口编程,能够循环发送数据,想具体到us级别,不需要设置ms发送。所以想用一个线程一直发送。

关键问题是碰到在线程循环发送竟然发不出去,见鬼了。。。最后找到问题是要在每次发送后要判断waitForBytesWritten是否发送成功,否则串口再也发不出去了,这很关键。

if(!serial.waitForBytesWritten())   //这一句很关键,决定是否能发送成功
{
    qDebug()<<"serial write failed";
}

程序界面:

QT5串口编程----线程循环发送不成功问题_第1张图片

测试效果:我这里测试用了虚拟串口(vspd)虚拟了两个串口来测试:效果如图:

QT5串口编程----线程循环发送不成功问题_第2张图片

 

话不多说,直接贴代码。

首先是mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 
#include 
#include 
#include 

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
public:
    void setAllState(bool state);
    void fillPortsParameters();
    QSerialPort serial;

protected:
    void run();
    void startThread();
    void stopThread();

private slots:
    void Serial_Read();

    void on_SerialClearRecButton_clicked();

    void on_SerialSendDataButton_clicked();

    void on_SeribalCheckButton_clicked();

    void on_SerialOpenButton_clicked();

    void on_SendTextEdit_textChanged();

    void on_LoopPushButton_clicked();


private:
    Ui::MainWindow *ui;
    std::atomic m_bRunThread = false;
};
#endif // MAINWINDOW_H

然后是mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include 
#include 
#include 
#include 

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


    //发送按键失能
    ui->SerialSendDataButton->setEnabled(false);
    ui->LoopPushButton->setEnabled(false);


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

    //设置所有下拉框失能;
    setAllState(false);
    //加入设置参数
    fillPortsParameters();
}

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



// 串口读取数据函数
void MainWindow:: Serial_Read()
{
//    QByteArray buf;
//    buf = serial.readAll();
//    if(!buf.isEmpty())//如果读到的数据不为空
//    {
//       ui->ReceiveTextEdit->insertPlainText(buf);
//     }
//     buf.clear();
    QByteArray recv;
    recv = serial.readAll();
    QString recv_string = recv;
    qDebug() << recv_string<ReceiveTextEdit->append(recv_string);
}


void MainWindow::on_SerialClearRecButton_clicked()
{
    ui->ReceiveTextEdit->clear();

}

void MainWindow::on_SerialSendDataButton_clicked()
{
    if(serial.isOpen())
    {
        //获取界面上的数据并转换成utf8格式的字节流
        QByteArray data = ui->SendTextEdit->toPlainText().toUtf8();
        qDebug()<SendTextEdit->toPlainText().toUtf8();
        serial.write(data);
        if(!serial.waitForBytesWritten())   //这一句很关键,决定是否能发送成功
        {
             qDebug()<<"serial write error";
        }
//        QThread::msleep(100);
    };
    qDebug()<<"loopsend thread quit";
}


void MainWindow::on_LoopPushButton_clicked()
{
    if(ui->LoopPushButton->text() == "LoopSend")
    {
        ui->LoopPushButton->setText(tr("STOP"));
        startThread();
    }
    else
    {
         ui->LoopPushButton->setText(tr("LoopSend"));
         stopThread();
    }
}


void MainWindow::on_SeribalCheckButton_clicked()
{
    ui->SerialNumberComb->clear();
    //通过QSerialPortInfo查找可用串口
    foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
    {
        ui->SerialNumberComb->addItem(info.portName());
    }
    if(ui->SerialNumberComb->currentIndex() != -1)
    {
        ui->SerialBaudrateComb->setEnabled(true);
        ui->SerialDataBitComb->setEnabled(true);
        ui->SerialParityBitComb->setEnabled(true);
        ui->SerialStopBitComb->setEnabled(true);
        ui->SerialFlowControlComb->setEnabled(true);
    }

}

void MainWindow::on_SerialOpenButton_clicked()
{
    if(ui->SerialOpenButton->text()==QString("打开串口"))
    {
        if(!serial.isOpen())
        {
            //设置串口名
            serial.setPortName(ui->SerialNumberComb->currentText());
            //设置波特率
            serial.setBaudRate(static_cast(ui->SerialBaudrateComb->itemData(ui->SerialBaudrateComb->currentIndex()).toInt()));
            //设置数据位数
            serial.setDataBits(static_cast(ui->SerialDataBitComb->itemData(ui->SerialDataBitComb->currentIndex()).toInt()));
            //设置奇偶校验
            serial.setParity(static_cast(ui->SerialParityBitComb->itemData(ui->SerialParityBitComb->currentIndex()).toInt()));
            //设置停止位
            serial.setStopBits(static_cast(ui->SerialStopBitComb->itemData(ui->SerialStopBitComb->currentIndex()).toInt()));
            //设置流控制
            serial.setFlowControl(static_cast(ui->SerialFlowControlComb->itemData(ui->SerialFlowControlComb->currentIndex()).toInt()));
            //打开串口
            if(!serial.open(QIODevice::ReadWrite))
            {
                QMessageBox::about(NULL,"提示","无法打开串口!");
                return;
            }
            setAllState(false);
            ui->SerialNumberComb->setEnabled(false);
            ui->SerialOpenButton->setText(QString("关闭串口"));
        }
    }
    else
    {
        if(serial.isOpen())
        {
            //关闭串口
            serial.close();
            //设置串口参数可设置
            setAllState(true);
            stopThread();
            ui->SerialNumberComb->setEnabled(true);
            ui->SerialOpenButton->setText(QString("打开串口"));
        }
    }

}


void MainWindow::setAllState(bool state)
{
    if(state)
    {
        ui->SerialBaudrateComb->setEnabled(true);
        ui->SerialDataBitComb->setEnabled(true);
        ui->SerialParityBitComb->setEnabled(true);
        ui->SerialStopBitComb->setEnabled(true);
        ui->SerialFlowControlComb->setEnabled(true);
    }
    else
    {
        ui->SerialBaudrateComb->setEnabled(false);
        ui->SerialDataBitComb->setEnabled(false);
        ui->SerialParityBitComb->setEnabled(false);
        ui->SerialStopBitComb->setEnabled(false);
        ui->SerialFlowControlComb->setEnabled(false);
    }

}

void MainWindow::fillPortsParameters()
{
    ui->SerialBaudrateComb->addItem(QStringLiteral("9600"), QSerialPort::Baud9600);
    ui->SerialBaudrateComb->addItem(QStringLiteral("19200"), QSerialPort::Baud19200);
    ui->SerialBaudrateComb->addItem(QStringLiteral("38400"), QSerialPort::Baud38400);
    ui->SerialBaudrateComb->addItem(QStringLiteral("38400"), QSerialPort::Baud57600);
    ui->SerialBaudrateComb->addItem(QStringLiteral("115200"), QSerialPort::Baud115200);

    ui->SerialDataBitComb->addItem(QStringLiteral("5"), QSerialPort::Data5);
    ui->SerialDataBitComb->addItem(QStringLiteral("6"), QSerialPort::Data6);
    ui->SerialDataBitComb->addItem(QStringLiteral("7"), QSerialPort::Data7);
    ui->SerialDataBitComb->addItem(QStringLiteral("8"), QSerialPort::Data8);
    ui->SerialDataBitComb->setCurrentIndex(3);

    ui->SerialParityBitComb->addItem(tr("None"), QSerialPort::NoParity);
    ui->SerialParityBitComb->addItem(tr("Even"), QSerialPort::EvenParity);
    ui->SerialParityBitComb->addItem(tr("Odd"), QSerialPort::OddParity);
    ui->SerialParityBitComb->addItem(tr("Mark"), QSerialPort::MarkParity);
    ui->SerialParityBitComb->addItem(tr("Space"), QSerialPort::SpaceParity);

    ui->SerialStopBitComb->addItem(QStringLiteral("1"), QSerialPort::OneStop);
#ifdef Q_OS_WIN
    ui->SerialStopBitComb->addItem(tr("1.5"), QSerialPort::OneAndHalfStop);
#endif
    ui->SerialStopBitComb->addItem(QStringLiteral("2"), QSerialPort::TwoStop);

    ui->SerialFlowControlComb->addItem(tr("None"), QSerialPort::NoFlowControl);
    ui->SerialFlowControlComb->addItem(tr("RTS/CTS"), QSerialPort::HardwareControl);
    ui->SerialFlowControlComb->addItem(tr("XON/XOFF"), QSerialPort::SoftwareControl);

}

void MainWindow::on_SendTextEdit_textChanged()
{
    if(ui->SendTextEdit->toPlainText().toUtf8() == "")
    {
         ui->SerialSendDataButton->setEnabled(false);
         ui->LoopPushButton->setEnabled(false);
    }
    else
    {
        ui->SerialSendDataButton->setEnabled(true);
        ui->LoopPushButton->setEnabled(true);
    }
}



再然后是 main.cpp

#include "mainwindow.h"

#include 

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

 

程序源码放在这个地址,大家可以去下载。

https://download.csdn.net/download/u010505080/12361152

你可能感兴趣的:(QT)