完整的Qt5串口通信

Qt5自带串口通信类,可以直接使用<QSerialPort>

包含的头文件
#include<QtSerialPort/QSerialPort>
#include<QtSerialPort/QSerialPortInfo>

,来进行串口通信。

下面分享一下自己在开发中的使用方法。

一、获取串口

void MainWindow::listSerialPorts()
{
    foreach (const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
    {
        QSerialPort serial;
        serial.setPort(info);
        if(serial.open(QIODevice::ReadWrite))
        {
            ui->comComboBox->addItem(serial.portName());
            serial.close();
        }
    }
}

二、打开串口

void MainWindow::on_openBtn_clicked()
{
    if(ui->openBtn->text()=="打开串口")
    {
        ui->openBtn->setText("关闭串口");
        btnSerialEnabledOrDisabled(false);
        ui->sendBtn->setEnabled(true);
        ui->statusBar->showMessage(ui->comComboBox->currentText()+" 串口打开!");

        if(serial==NULL)
            serial = new QSerialPort;
        serial->setPortName(ui->comComboBox->currentText());
        if(!serial->isOpen())
            serial->open(QIODevice::ReadWrite);
        //设置波特率
        switch(ui->baudRateComBox->currentIndex())
        {
        case 0:
            serial->setBaudRate(QSerialPort::Baud9600);break;
        case 1:
            serial->setBaudRate(QSerialPort::Baud19200);break;
        case 2:
            serial->setBaudRate(QSerialPort::Baud38400);break;
        case 3:
            serial->setBaudRate(QSerialPort::Baud57600);break;
        case 4:
            serial->setBaudRate(QSerialPort::Baud115200);break;
        }
        //设置数据位
        switch(ui->dataBitComBox->currentIndex())
        {
        case 0:
            serial->setDataBits(QSerialPort::Data5);break;
        case 1:
            serial->setDataBits(QSerialPort::Data6);break;
        case 2:
            serial->setDataBits(QSerialPort::Data7);break;
        case 3:
            serial->setDataBits(QSerialPort::Data8);break;
        }
        //设置校验位
        switch (ui->parityComBox->currentIndex())
        {
        case 0:
            serial->setParity(QSerialPort::NoParity);break;
        case 1:
            serial->setParity(QSerialPort::EvenParity);break;
        case 2:
            serial->setParity(QSerialPort::OddParity);break;
        case 3:
            serial->setParity(QSerialPort::MarkParity);break;
        case 4:
            serial->setParity(QSerialPort::SpaceParity);break;
        }
        //设置流控
        switch (ui->streamCtrlComBox->currentIndex())
        {
        case 0:
            serial->setFlowControl(QSerialPort::NoFlowControl);break;
        case 1:
            serial->setFlowControl(QSerialPort::HardwareControl);break;// RTS/CTS   硬件流控
        case 2:
            serial->setFlowControl(QSerialPort::SoftwareControl);break;//   XON/XOFF   软件控制数据流传输
        }
        //设置停止位
        switch(ui->stopBitBtn->currentIndex())
        {
        case 0:
            serial->setStopBits(QSerialPort::OneStop);break;
            break;
        case 1:
            serial->setStopBits(QSerialPort::OneAndHalfStop);break;
            break;
        case 2:
            serial->setStopBits(QSerialPort::TwoStop);break;
            break;
        }
        sct->slotsetFlag(true);
    }
    else
    {
        ui->openBtn->setText("打开串口");
        btnSerialEnabledOrDisabled(true);
        ui->spinTimeBox->setEnabled(true);
        ui->cmdComboBox->setEnabled(true);
        ui->sendBtn->setEnabled(false);
        ui->statusBar->showMessage(ui->comComboBox->currentText()+" 串口关闭!");
        sct->slotsetFlag(false);
    }
}

三、读取串口数据

建议通信方法:通过信号槽的方式实现读取串口数据。

connect(serial,SIGNAL(readyRead()),this,SLOT(getSpData()));
connect(timer,SIGNAL(timeout()),this,SLOT(dealTimeOut()));

第一步:打开串口后,连接信号槽;

第二步:建一个定时器,每隔一段时间比如(20ms),在槽函数里面启动定时器,

void mainWindow::getSpData()
{
    timer->start(20);
    //QByteArray tmp;放在.h文件里   tmp即接收到的数据
    tmp.push_back(serial->readAll());

}

第三步:处理超时函数,超时函数里面需要对串口接收到的数据进行处理。

void mainWindow::dealTimeOut()
{
    timer->stop();
//此时再定义一个QString spData,并将tmp的数据赋值给spData。

    //在此处对接收的数据spData进行处理
    //....
}

四、串口写入数据

QByteArray b;
...
...
serial->write(b);

如果写入失败,需要在write之后加入serial->waitForBytesWritten()。

在子线程中,在write之后,必须要等待写出去完毕才执行下一步,否则线程跑到别的地方进行休眠就会把数据缓存到iodevice中:

五、串口关闭

serial->close();

六、建议

串口的发送数据和接收数据不要放在一个函数里面,如有必要可以发送和接收各一个线程。发送的数据和接收的数据分别处理,互不影响。

如遇字节转换参考该文章:https://blog.csdn.net/weixin_41882459/article/details/106232163


版权声明:本文为weixin_41882459原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。