<QT学习>QT中串口QSerialport类学习与使用

   QT5中已经增加了串口类QSrialPort,可以直接调用API函数进行快速开发。

 

 

 

 

 

 

 

 

 

 

  注意qmake那边:QT += serialport。要把QT += serialport在加到.pro文件中

1. 获取串口信息

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    const auto infos = QSerialPortInfo::availablePorts();
    for (const QSerialPortInfo &info : infos)
        serialPortComboBox->addItem(info.portName());
}
  • QSerialPortInfo::availablePorts()

 

函数的功能时会检测当前电脑上串行端口,并且返回系统上串行端口的信息。

之后将获取到的信息加入Qcombobox下拉选项框中。本例中只添加了串口的名字即COM4。

 

2.设置串口参数并开启串口

void Dialog::openSerial()
{
    if(runButton->text() == tr("开启"))
    {
        serial = new QSerialPort();

        //port name
        serial->setPortName(serialPortComboBox->currentText());

        //open
        serial->open(QIODevice::ReadWrite);

        serial->setBaudRate(115200);
        serial->setDataBits(QSerialPort::Data8);
        serial->setStopBits(QSerialPort::OneStop);
        serial->setFlowControl(QSerialPort::NoFlowControl);

     /* 一定要写,不然串口接收不到数据 */ connect(serial, SIGNAL(readyRead()),
this, SLOT(readParam())); runButton->setText("关闭"); } else { serial->clear(); serial->close(); serial->deleteLater(); runButton->setText("开启"); } }connect(serial, SIGNAL(readyRead()), this, SLOT(readParam()));
  该函数是启动串口接收功能。即当串口有数据时,readyRead()信号就会被抛出。对应的readParam()即QT中所定义的槽就会被调用。

注意:
  readyRead()信号是有数据就直接抛出,在实际数据交互中,往往一帧数据有很多字节。这意味着我们一帧数据数据会触发多次信号。应当在对数据进行操作时候对数据进行校验。


3.串口发送数据
serial->write(sendData);

sendData为QByteArray类所创建的对象,即数据缓存区。

 

4.串口接收数据
g_RecBuf.append(serial->readAll());

  readAll函数会读取当前设备所有剩余数据,并将它作为字节数组返回。

以上实例源码:

dialog.cpp

#include "dialog.h"
#include <QDebug>
#include <QThread>
#include <QTimer>

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    serialPortComboBox = new QComboBox();
    readParaBox = new QComboBox();
    writeParaBox = new QComboBox();
    runButton = new QPushButton(tr("开启"));
    readPara = new QPushButton(tr("读取参数"));
    writePara = new QPushButton(tr("下发参数"));
    onlyOneRead = new QPushButton(tr("一键读取"));
    onlyOneWrite = new QPushButton(tr("一键下发"));
    cmd = readFlag;

    timer = new QTimer();

    /* add comprot into combobox item */
    const auto infos = QSerialPortInfo::availablePorts();
    for (const QSerialPortInfo &info : infos)
        serialPortComboBox->addItem(info.portName());

    readParaBox->addItem(tr("读取参数地址1"));
    readParaBox->addItem(tr("读取参数地址2"));
    readParaBox->addItem(tr("读取参数地址3"));
    readParaBox->addItem(tr("读取参数地址4"));
    readParaBox->addItem(tr("读取参数地址5"));

    writeParaBox->addItem(tr("下发参数地址1"));
    writeParaBox->addItem(tr("下发参数地址2"));
    writeParaBox->addItem(tr("下发参数地址3"));
    writeParaBox->addItem(tr("下发参数地址4"));
    writeParaBox->addItem(tr("下发参数地址5"));

    auto mainLayout = new QGridLayout;
    mainLayout->addWidget(serialPortComboBox, 0, 0);
    mainLayout->addWidget(runButton, 0, 1);
    mainLayout->addWidget(readParaBox,1,0);
    mainLayout->addWidget(readPara, 1, 1);
    mainLayout->addWidget(writeParaBox,2,0);
    mainLayout->addWidget(writePara, 2, 1);
    mainLayout->addWidget(onlyOneRead,3,0);
    mainLayout->addWidget(onlyOneWrite,3,1);
    setLayout(mainLayout);

    connect(runButton, &QPushButton::clicked, this, &Dialog::openSerial);
    connect(readPara, &QPushButton::clicked, this, &Dialog::sendCmd);
    connect(writePara, &QPushButton::clicked, this, &Dialog::writeParam);
    connect(timer, SIGNAL(timeout()), this, SLOT(timerStop()));
    connect(onlyOneRead,&QPushButton::clicked,this,&Dialog::oneRead);
    connect(onlyOneWrite,&QPushButton::clicked,this,&Dialog::oneWrite);
}

void Dialog::openSerial()
{
    if(runButton->text() == tr("开启"))
    {
        serial = new QSerialPort();

        //port name
        serial->setPortName(serialPortComboBox->currentText());

        //open
        serial->open(QIODevice::ReadWrite);

        serial->setBaudRate(115200);
        serial->setDataBits(QSerialPort::Data8);
        serial->setStopBits(QSerialPort::OneStop);
        serial->setFlowControl(QSerialPort::NoFlowControl);

        connect(serial, SIGNAL(readyRead()), this, SLOT(readParam()));

        runButton->setText("关闭");
    }
    else
    {
        serial->clear();
        serial->close();
        serial->deleteLater();

        runButton->setText("开启");
    }
}

void Dialog::writeParam(void)
{
    QByteArray sendData;
    sendData.resize(1026);

    QString strWriteFile = writeParaBox->currentText();
    strWriteFile.append(".dat");

    if(strWriteFile == "下发参数地址1.dat")
    {
        file.setFileName("读取参数地址1.dat");
        if(file.open(QFile::ReadOnly))
        {
            sendData = file.readAll();
            serial->write(sendData);
        }
    }
    else if(strWriteFile == "下发参数地址2.dat")
    {
        file.setFileName("读取参数地址2.dat");
        if(file.open(QFile::ReadOnly))
        {
            sendData = file.readAll();
            serial->write(sendData);
        }
    }
    else if(strWriteFile == "下发参数地址3.dat")
    {
        file.setFileName("读取参数地址3.dat");
        if(file.open(QFile::ReadOnly))
        {
            sendData = file.readAll();
            serial->write(sendData);
        }
    }
    else if(strWriteFile == "下发参数地址4.dat")
    {
        file.setFileName("读取参数地址4.dat");
        if(file.open(QFile::ReadOnly))
        {
            sendData = file.readAll();
            serial->write(sendData);
        }
    }
    else if(strWriteFile == "下发参数地址5.dat")
    {
        file.setFileName("读取参数地址5.dat");
        if(file.open(QFile::ReadOnly))
        {
            sendData = file.readAll();
            serial->write(sendData);
        }
    }
    file.close();
    sendData.clear();
}

void Dialog::timerStop(void)
{
    g_RecBuf.prepend(0xBB);

    timer->stop();
    {
        QByteArray leftAck = g_RecBuf.left(2);
        QByteArray rightAck = g_RecBuf.right(1);

        QByteArray byte1;
        QByteArray byte2;

        byte1.append(0xBB);
        byte1.append(0xAA);
        byte2.append(0xFF);

        if(g_RecBuf.size() > 30)
        {
            Dialog::saveDataToFile(g_RecBuf);
        }
        else if(leftAck == byte1 && rightAck == byte2 && cmd == writeFlag)
        {
            cmd = readFlag;
            msglabel = new QLabel();
            QMessageBox::question(this,tr("提示"),tr("下发参数成功"), QMessageBox::Ok);
        }
    }
    g_RecBuf.clear();
}

void Dialog::readParam()
{
    timer->start(100);
    g_RecBuf.append(serial->readAll());
}

/* Function: Dialog::saveDataToFile
 * Describe: Save the data from serial into File
*/
void Dialog::saveDataToFile(QByteArray &data)
{
    if(cmd == readFlag)
    {
        QString strFileName = readParaBox->currentText();

        file.setFileName(strFileName.append(".dat"));
        if(file.open(QFile::WriteOnly))
        {
            file.write(data);
        }
        file.close();
    }

    if(cmd != readFlag)
    {
        switch (cmd) {
        case cmd1:
            file.setFileName("读取参数地址1.dat");
            if(file.open(QFile::WriteOnly))
            {
                file.write(data);
            }
            file.close();
            Dialog::oneRead();
            break;

        case cmd2:
            file.setFileName("读取参数地址2.dat");
            if(file.open(QFile::WriteOnly))
            {
                file.write(data);
            }
            file.close();
            Dialog::oneRead();
            break;

        case cmd3:
            file.setFileName("读取参数地址3.dat");
            if(file.open(QFile::WriteOnly))
            {
                file.write(data);
            }
            file.close();
            Dialog::oneRead();
            break;

        case cmd4:
            file.setFileName("读取参数地址4.dat");
            if(file.open(QFile::WriteOnly))
            {
                file.write(data);
            }
            file.close();
            Dialog::oneRead();
            break;

        case cmd5:
            file.setFileName("读取参数地址5.dat");
            if(file.open(QFile::WriteOnly))
            {
                file.write(data);
            }
            file.close();
            cmd = readFlag;
            break;
        default:
            break;
        }
    }
}

void Dialog::sendCmd(void)
{
    QByteArray sendpara;

    unsigned char zero = 0x00;

    if(readParaBox->currentText() == tr("读取参数地址1"))
    {
        sendpara.append(0xAA);
        sendpara.append(0x33);
        sendpara.append(0x01);
        sendpara.append(zero);
        sendpara.append(zero);
        sendpara.append(zero);
        sendpara.append(0xFF);
    }
    else if(readParaBox->currentText() == tr("读取参数地址2"))
    {
        sendpara.append(0xAA);
        sendpara.append(0x33);
        sendpara.append(0x02);
        sendpara.append(zero);
        sendpara.append(zero);
        sendpara.append(zero);
        sendpara.append(0xFF);
    }
    else if(readParaBox->currentText() == tr("读取参数地址3"))
    {
        sendpara.append(0xAA);
        sendpara.append(0x33);
        sendpara.append(0x03);
        sendpara.append(zero);
        sendpara.append(zero);
        sendpara.append(zero);
        sendpara.append(0xFF);
    }
    else if(readParaBox->currentText() == tr("读取参数地址4"))
    {
        sendpara.append(0xAA);
        sendpara.append(0x33);
        sendpara.append(0x04);
        sendpara.append(zero);
        sendpara.append(zero);
        sendpara.append(zero);
        sendpara.append(0xFF);
    }
    else if(readParaBox->currentText() == tr("读取参数地址5"))
    {
        sendpara.append(0xAA);
        sendpara.append(0x33);
        sendpara.append(0x05);
        sendpara.append(zero);
        sendpara.append(zero);
        sendpara.append(zero);
        sendpara.append(0xFF);
    }

    serial->write(sendpara);
    sendpara.clear();
}

void Dialog::oneRead(void)
{
    QByteArray cmdArray;
    unsigned char zero = 0x00;

    switch (cmd) {
    case readFlag:
        cmdArray.append(0xAA);
        cmdArray.append(0x33);
        cmdArray.append(0x01);
        cmdArray.append(zero);
        cmdArray.append(zero);
        cmdArray.append(zero);
        cmdArray.append(0xFF);
        cmd = cmd1;

        serial->write(cmdArray);
        cmdArray.clear();
        break;

    case cmd1:
        cmdArray.append(0xAA);
        cmdArray.append(0x33);
        cmdArray.append(0x02);
        cmdArray.append(zero);
        cmdArray.append(zero);
        cmdArray.append(zero);
        cmdArray.append(0xFF);
        cmd = cmd2;

        serial->write(cmdArray);
        cmdArray.clear();
        break;

    case cmd2:
        cmdArray.append(0xAA);
        cmdArray.append(0x33);
        cmdArray.append(0x03);
        cmdArray.append(zero);
        cmdArray.append(zero);
        cmdArray.append(zero);
        cmdArray.append(0xFF);
        cmd = cmd3;

        serial->write(cmdArray);
        cmdArray.clear();
        break;

    case cmd3:
        cmdArray.append(0xAA);
        cmdArray.append(0x33);
        cmdArray.append(0x04);
        cmdArray.append(zero);
        cmdArray.append(zero);
        cmdArray.append(zero);
        cmdArray.append(0xFF);
        cmd = cmd4;

        serial->write(cmdArray);
        cmdArray.clear();
        break;

    case cmd4:
        cmdArray.append(0xAA);
        cmdArray.append(0x33);
        cmdArray.append(0x05);
        cmdArray.append(zero);
        cmdArray.append(zero);
        cmdArray.append(zero);
        cmdArray.append(0xFF);
        cmd = cmd5;

        serial->write(cmdArray);
        cmdArray.clear();
        break;
    }
}

void Dialog::oneWrite(void)
{
    QByteArray sendData;
    sendData.resize(1026);

    file.setFileName("读取参数地址1.dat");
    if(file.open(QFile::ReadOnly))
    {
        sendData = file.readAll();
        serial->write(sendData);
    }
    file.close();
    sendData.clear();

    file.setFileName("读取参数地址2.dat");
    if(file.open(QFile::ReadOnly))
    {
        sendData = file.readAll();
        serial->write(sendData);
    }
    file.close();
    sendData.clear();

    file.setFileName("读取参数地址3.dat");
    if(file.open(QFile::ReadOnly))
    {
        sendData = file.readAll();
        serial->write(sendData);
    }
    file.close();
    sendData.clear();


    file.setFileName("读取参数地址4.dat");
    if(file.open(QFile::ReadOnly))
    {
        sendData = file.readAll();
        serial->write(sendData);
    }
    file.close();
    sendData.clear();
#if 0
    file.setFileName("读取参数地址5.dat");
    if(file.open(QFile::ReadOnly))
    {
        sendData = file.readAll();
        serial->write(sendData);
    }
    file.close();
    sendData.clear();
#endif

    cmd = writeFlag;
}

Dialog::~Dialog()
{

}

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>

#include <QComboBox>
#include <QLabel>
#include <QPushButton>
#include <QGridLayout>
#include <QtSerialPort/QSerialPortInfo>
#include <QtSerialPort>
#include <QFile>
#include <QTextStream>
#include <QDateTime>
#include <QTimer>
#include <QMessageBox>

enum enumType
{
  readFlag,
  cmd1,
  cmd2,
  cmd3,
  cmd4,
  cmd5,
  writeFlag
};

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private slots:
    void openSerial(void);
    void writeParam(void);
    void sendCmd(void);
    void timerStop(void);
    void readParam(void);
    void oneRead(void);
    void oneWrite(void);

private:
    void saveDataToFile(QByteArray &data);


private:
    QComboBox *serialPortComboBox;
    QComboBox *readParaBox;
    QComboBox *writeParaBox;

    QPushButton *runButton;
    QPushButton *readPara;
    QPushButton *writePara;
    QPushButton *onlyOneRead;
    QPushButton *onlyOneWrite;

    QLabel *msglabel;
    QSerialPort *serial;
    QTimer *timer;
    QFile file;
    QByteArray g_RecBuf;

    unsigned int Flag;

    enumType cmd;
};


#endif // DIALOG_H

  运行效果:

   作用就是通过串口发送以及接收一些数据。

 

 

 

 

 

 

 




 

posted @ 2018-12-13 16:23  一个不知道干嘛的小萌新  阅读(2613)  评论(0编辑  收藏  举报