QT5 serial port host computer -- teach you to write 02 from scratch

Previous article: QT5 serial port host computer -- teach you to write 01 from scratch

Simple serial port programming

2.QSerialPort module configuration

QtSerialPort module of QT

Qt provides two C + + classes, QSerialPort and QSerialPortInfo.

Their functions are as follows:

QSerialPort: provides various interfaces for operating serial ports.

QSerialPortInfo: it can provide various information about the available serial ports in the computer.

Usage of QtSerialPort module

First, you need to add the following contents to the pro file:

QT += serialport    

Then execute qmake. If it is not executed, an error will be reported when adding a header file later.

Add a new * * C + + * * class to the project,

Select C++ Class

Name it Serial and click next to generate the corresponding file

In the generated serial.h, do the following

#ifndef SERIAL_H
#define SERIAL_H

#include <QObject>
#Include < qserialport > / / add the header file of the serial port class
#include <QSerialPortInfo> 	 // Add header file of serial port information

class Serial : public QObject
{
    Q_OBJECT
public:
    explicit Serial(QObject *parent = nullptr);
    ~Serial(void);			//Add destructor
    void SerialOpen();		//Add open serial port function
    void SerialClose();		//Add close serial port function
private:
    QSerialPort* MySerial;  //Add serial port class member

signals:
    void SetInfo(QString info);
    void isnoSerialOpen();
};

#endif // SERIAL_H


Place the cursor behind the function and press the shortcut key alt + enter

    ~Serial(void);			//Add destructor
    void SerialOpen();		//Add open serial port function
    void SerialClose();		//Add close serial port function

When the following picture appears, press enter to define the function in the cpp file.

Dynamic diagram display.

~Serial(void); Used to delete the new variable in the program

void SerialOpen(); And void SerialClose(); Is used to open the serial port.

First, instantiate MySerial in the cpp file.

Then, place the mouse over MySerial and press the shortcut key F1 to open the help document of QSerialPort. Public Functions found

Open Detailed Description

From the help document, we can see that we need to configure the serial port.

Configure serial port parameters

The operation steps are as follows:

1. First, you need to set the serial port name to be opened, which can be configured through * * setPortName() or setPort() * * here

2. Then open the serial port in one of the read only (R / O), write only (w / O), or read write (R / W) modes by using the open() function

3. Then, check whether the serial port is opened (and no other process or thread opens the serial port. If so, close the serial port and reopen it)

4. Finally, configure serial port parameters, such as serial port name, baud rate, data bit, check bit, stop bit and flow control bit

The configuration functions are as follows:

 void setPortName(const QString &name) 
 bool setBaudRate(qint32 baudRate, QSerialPort::Directions directions = AllDirections)
 bool setDataBits(QSerialPort::DataBits dataBits)
 bool setParity(QSerialPort::Parity parity)
 bool setStopBits(QSerialPort::StopBits stopBits)
 bool setFlowControl(QSerialPort::FlowControl flowControl)

First, we need the name parameter and baudRate parameter of QString and qint32, which are obtained through the Qcombobox option of the ui interface. Because multithreading is used, it cannot be called directly. Therefore, here, the parameters are passed by constructing the structure and passing the structure.

Right click the project and add a new cpp header file

Set the header file name to SerialInfo.h. click next to finish.

Add SerialInfo.h as follows.

#ifndef SERIALINFO_H
#define SERIALINFO_H
#include <QVector>
#include <QMetaType>

typedef struct SerialInfos         //Serial port configuration information
{
     QString comName;    //Serial port name
     qint32 baudRate;     //Baud rate
     qint32 dataBits;     //Data bit
     qint32 parity;       //Check bit
     qint32 stopBits;     //Stop bit
     qint32 flowControl;  //Flow control position
     qint32 Encode;       //Coding format

}Sinfo;


//Pass Q_ DECLARE_ After the metatype is declared, you can set the custom type to QVariant.
Q_DECLARE_METATYPE(Sinfo);

#endif // SERIALINFO_H

Add header file in serial.h

#include "SerialInfo.h"

And add private members

private:
    QSerialPort* MySerial;
    Sinfo *info=nullptr;    //Serial port configuration
	QString InfoSet;        //Storage serial port configuration

The modified serial.h is as follows

#ifndef SERIAL_H
#define SERIAL_H

#include <QObject>
#Include < qserialport > / / add the header file of the serial port class
#include <QSerialPortInfo> 	 // Add header file of serial port information
#include "SerialInfo.h"

class Serial : public QObject
{
    Q_OBJECT
public:
    explicit Serial(QObject *parent = nullptr);
    ~Serial(void);			//Add destructor
    void SerialOpen();		//Add open serial port function
    void SerialClose();		//Add close serial port function
private:
    QSerialPort* MySerial;  //Add serial port class member
    Sinfo *info=nullptr;    //Serial port configuration
    QString InfoSet;        //Storage serial port configuration
signals:
    void SetInfo(QString info); //Send serial port configuration signal
    void isnoSerialOpen();	//Send serial port opening failure signal
};

#endif // SERIAL_H

Next, operate in SerialOpen.

First, judge whether the serial port is open. If it is already open, close it. SerialClose() is called here (see the SerialClose section below for details)

this->SerialClose();

Then set the serial port name

MySerial->setPortName(QString(info->comName));

Then set the serial port open mode and R/W mode. If the setting fails, send an error message, and then return.

if(!MySerial->open(QIODevice::ReadWrite))//Try to open the serial port in ReadWrite mode
    {
        emit isnoSerialOpen();  //Send open failed flag
        return;
    }

Where isnoSerialOpen() is set to send an open failure signal.

Then set the baud rate through Info - > baudrate

MySerial->setBaudRate(qint32(info->baudRate));

Set the data bits here through the switch function, where setDataBits(); Use F1 to view the parameters in. The specific operation steps are as follows.

Use the same method to set the inspection bit, stop bit and flow control bit.

The above operation steps are implemented in * * SerialOpen() * * and the specific code is as follows:

void Serial::SerialOpen()
{
    this->SerialClose();
    MySerial->setPortName(QString(info->comName));
    InfoSet=QString::fromLocal8Bit("Serial port:"); //InfoSet stores the serial port setting information and sends it to mainWidget
    InfoSet.append(QString(info->comName));
    if(!MySerial->open(QIODevice::ReadWrite))//Try to open the serial port in ReadWrite mode
    {
        emit isnoSerialOpen();  //Send open failed flag
        return;
    }
    //set baud rate
    bool Bflag = MySerial->setBaudRate(qint32(info->baudRate));
        if(Bflag){
            InfoSet.append(QString::fromLocal8Bit(" Baud rate:"));
            //The first parameter is an int variable, and the second parameter 10 represents the conversion to hexadecimal number
            QString baudRateinfo = QString::number(int(info->baudRate),10);
            InfoSet.append(baudRateinfo);
        }
        else{
            InfoSet.QString::fromLocal8Bit("Baud rate:Unknown");
        };
        //set data bit
        switch (info->dataBits) {
                case 0:
                       MySerial->setDataBits(QSerialPort::Data5);
                       InfoSet.append(QString::fromLocal8Bit(" Data bit:5"));
                       break;
                case 1:
                       MySerial->setDataBits(QSerialPort::Data6);
                       InfoSet.append(QString::fromLocal8Bit(" Data bit:6"));
                       break;
                case 2:
                       MySerial->setDataBits(QSerialPort::Data7);
                       InfoSet.append(QString::fromLocal8Bit(" Data bit:7"));
                       break;
                case 3:
                       MySerial->setDataBits(QSerialPort::Data8);
                       InfoSet.append(QString::fromLocal8Bit(" Data bit:8"));
                       break;
                default:
                        MySerial->setDataBits(QSerialPort::UnknownDataBits);
                        InfoSet.append(QString::fromLocal8Bit(" Data bit:Unknown"));
                        break;
                }
        //Set check bit
        switch (info->parity) {
                case 0:
                    MySerial->setParity(QSerialPort::EvenParity);
                    InfoSet.append(QString::fromLocal8Bit(" Check bit:Even"));
                    break;
                case 1:
                    MySerial->setParity(QSerialPort::MarkParity);
                    InfoSet.append(QString::fromLocal8Bit(" Check bit:Mark"));
                    break;
                case 2:
                    MySerial->setParity(QSerialPort::NoParity);
                    InfoSet.append(QString::fromLocal8Bit(" Check bit:None"));
                    break;
                case 3:
                    MySerial->setParity(QSerialPort::OddParity);
                    InfoSet.append(QString::fromLocal8Bit(" Check bit:Odd"));
                    break;
                case 4:
                    MySerial->setParity(QSerialPort::SpaceParity);
                    InfoSet.append(QString::fromLocal8Bit(" Check bit:Space"));
                    break;
                default:
                    MySerial->setParity(QSerialPort::UnknownParity);
                    InfoSet.append(QString::fromLocal8Bit(" Check bit:Unknown"));
                    break;
                }
        //Set stop bit
        switch (info->stopBits) {
                case 0:
                    MySerial->setStopBits(QSerialPort::OneStop);
                    InfoSet.append(QString::fromLocal8Bit(" Stop bit:1"));
                    break;
                case 1:
                    MySerial->setStopBits(QSerialPort::OneAndHalfStop);
                    InfoSet.append(QString::fromLocal8Bit(" Stop bit:1.5"));
                    break;
                case 2:
                    MySerial->setStopBits(QSerialPort::TwoStop);
                    InfoSet.append(QString::fromLocal8Bit(" Stop bit:2"));
                    break;
                default:
                    MySerial->setStopBits(QSerialPort::UnknownStopBits);
                    InfoSet.append(QString::fromLocal8Bit(" Stop bit:Unknown"));
                    break;
                }
        //Set flow control position
        switch (info->flowControl) {
                case 0:
                    MySerial->setFlowControl(QSerialPort::NoFlowControl);
                    InfoSet.append(QString::fromLocal8Bit(" Flow control position:None"));
                    break;
                case 1:
                    MySerial->setFlowControl(QSerialPort::HardwareControl);
                    InfoSet.append(QString::fromLocal8Bit(" Flow control position:Hardware"));
                    break;
                case 2:
                    MySerial->setFlowControl(QSerialPort::SoftwareControl);
                    InfoSet.append(QString::fromLocal8Bit(" Flow control position:Software"));
                    break;
                default:
                    MySerial->setFlowControl(QSerialPort::UnknownFlowControl);
                    InfoSet.append(QString::fromLocal8Bit(" Flow control position:Unknown"));
                    break;
                }
        emit SetInfo(InfoSet);//Send serial port configuration signal
}

Add * * SerialClose() * * function. The details are as follows:

void Serial::SerialClose()
{
    if(MySerial->isOpen())//If the serial port has been opened, close it first
    {
        MySerial->clear();
        MySerial->close();
    }
}

Add receiving serial port configuration parameter function. This function mainly receives the serial port parameters selected from the ui interface and saves them in info. As mentioned earlier, the parameters are passed through the structure, so the formal parameters of the structure should be added when constructing the constructor.

Add the public function * void RecvSerialConfig(Sinfo data).

public:
	void RecvSerialConfig(Sinfo *data);  //Receive serial port configuration parameter function

Press alt+enter to add the definition in serial.cpp.

void Serial::RecvSerialConfig(Sinfo *data)
{
    if(info!=nullptr)   //Delete original memory space
    {
        delete info;
    }
    this->info = new Sinfo;//To prevent memory leakage, delete info when closing;
    //Receiving parameter setting
    this->info->Encode=data->Encode;
    this->info->baudRate=data->baudRate;
    this->info->comName=data->comName;
    this->info->dataBits=data->dataBits;
    this->info->flowControl=data->flowControl;
    this->info->parity=data->parity;
    this->info->stopBits=data->stopBits;
}

It should be noted here that when applying for memory space, it must be released after the end, otherwise it is easy to cause memory leakage. Therefore, in * * ~ Serial(void); Add delete info to the**

**~Serial(void);** The functions are as follows:

Serial::~Serial()
{
    delete info;
}

Configure send and receive functions

After configuring the opening and closing functions, configure the sending and receiving functions here

Add the public function void SendData(QByteArray data, bool hexflag) in serial.h; And void RecvData();. Add the signal void isRecvData(QByteArray);

public:
    void SendData(QByteArray data, bool hexflag); //send data
    void RecvData(); //receive data 
signals:
    void isRecvData(QByteArray); //Receive data signal

Press alt+enter to add the definition in serial.cpp.

void SendData(QByteArray data, bool hexflag); In the function, data is the data transmitted by the ui interface, and hexflag is whether it is sent through hex mode.

isRecvData(QByteArray); It is to transmit the data received by the serial port to the ui.

The specific functions are as follows:

void Serial::SendData(QByteArray data, bool hexflag)
{
    if(data.isEmpty())
    {
        return;//Exit without reading data
    }
    if(hexflag==true)
    {   //hex mode direct transmission
        MySerial->write(data);
    }
    else{ //Determine whether the encoding format is sending
         data=SetCodeType(data,info->Encode); //First convert the data encoding format according to the encoding
         MySerial->write(data);
    }
}

void Serial::RecvData()
{
    QByteArray info = MySerial->readAll();
    if(info.isEmpty())
     {
       return ;//Exit without reading data
     }
    emit isRecvData(info);
}

Here * * SetCodeType()** Function sets the data encoding format for the defined function. See the configuration coding format function for the specific implementation method.

Configure encoding format function

Add a new C + + class to the project, right-click the project and select ADD NEW.

Select C++ Class

Select according to the following figure, and click next to finish.

Modify codetype.h as follows:

#ifndef CODETYPE_H
#define CODETYPE_H

#include <QString>
#include <QTextCodec>

//List of encoding formats
typedef enum
{
    ASCII = 0,
    Utf8,     //Utf8 encoding format
    Utf16,    //Utf16 encoding format
    GBK,  //GBK coding format, compatible with GBK18030 and GB2312
    Big5,     //Big5
    ShiftJIS
}CodeType;
//Set encoding format
QByteArray SetCodeType(QByteArray const &data,qint32 control);
//Parsing encoding format
QByteArray GetCodeType(QByteArray const &data, qint32 control);
#endif // CODETYPE_H

Modify codetype.cpp as follows:

#include "codetype.h"
//code
QByteArray SetCodeType(const QByteArray &data, qint32 control)
{
    QByteArray tmpData;
    switch (control) {
        case ASCII: tmpData=QTextCodec::codecForName("latin1")->fromUnicode(data);break;
        case Utf8: tmpData= QTextCodec::codecForName("UTF-8")->fromUnicode(data);break;
        case Utf16: tmpData= QTextCodec::codecForName("UTF-16")->fromUnicode(data);break;
        case GBK: tmpData= QTextCodec::codecForName("GBK")->fromUnicode(data);break;
        case Big5: tmpData= QTextCodec::codecForName("Big5")->fromUnicode(data);break;
        case ShiftJIS: tmpData= QTextCodec::codecForName("Shift-JIS")->fromUnicode(data);break;
        default:;break;
    }
    return tmpData;
}

//decode
QByteArray GetCodeType(const QByteArray &data, qint32 control)
{
    QString tmpData;
    switch (control) {
        case ASCII: tmpData= QTextCodec::codecForName("latin1")->toUnicode(data);break;
        case Utf8: tmpData= QTextCodec::codecForName("UTF-8")->toUnicode(data);break;
        case Utf16: tmpData= QTextCodec::codecForName("UTF-16")->toUnicode(data);break;
        case GBK: tmpData= QTextCodec::codecForName("GBK")->toUnicode(data);break;
        case Big5: tmpData= QTextCodec::codecForName("Big5")->toUnicode(data);break;
        case ShiftJIS: tmpData= QTextCodec::codecForName("Shift-JIS")->toUnicode(data);break;
        default:;break;
    }
    return tmpData.toUtf8(); //Set to Unicode format
}

QTextCodec is mainly used here. For details, please refer to the Qt help document, which is only briefly summarized here.

1. The header file * * #include * * needs to be included.

2.QTextCodec class is mainly used to convert data between non Unicode format and Unicode.

At this point, the QtSerialPort configuration is complete.

official account

Keywords: Qt

Added by Spikey on Thu, 28 Oct 2021 00:12:00 +0300