当前位置:网站首页>C2-qt serial port debugging assistant 2021.10.21

C2-qt serial port debugging assistant 2021.10.21

2022-06-22 02:44:00 Morning and evening rain

Qt Realize serial port debugging assistant

1. The goal is

Realize serial port debugging assistant , The interface style is concise , Configurable key communication parameters include , Baud rate 、 Stop bit 、 Data bits 、 Check bit ; We can use 16 Binary transmit data , With 16 Base or ascii Code receiving data , Support to save the received data to local txt.
notes : see FPGA Lower computer serial port code implementation , Please check out FPGA Serial port communication
download FPGA Serial communication engineering documents and codes , Please check out FPGA Serial port communication vivado engineering

2. step

2.1.pro Add , Serial port module .

The module Qt5 Support ,Qt4 I won't support it ;

QT += serialport

2.2 Serial port related classes

#include <QtSerialPort/QSerialPortInfo>
#include <QtSerialPort/QSerialPort>

QSerialPortInfo This class will get the serial port information , as follows :

        qDebug()<<"serialPortName:"<<info.portName();
        qDebug() << "Description : " << info.description();
        qDebug() << "Manufacturer: " << info.manufacturer();
        qDebug() << "Serial Number: " << info.serialNumber();
        qDebug() << "System Location: " << info.systemLocation();

QSerialPort There are many ways , As basic as open、close、read、write Method , And error handling 、 Set serial port parameters and other methods , Will coordinate the work , Jointly complete the operation of serial port sending and receiving .

2.3 Interface prototype construction

Some interface layout details , The typesetting principle is fully reflected in the following interface prototype with infinite fidelity , This setup does not require manual code .
 Insert picture description here

2.4 Interface logic

(1) call Init() function , The initialization function will complete the following functions
First, check the current online serial port device , And write it into the drop-down box ;
Initialize baud rate selection drop-down box , And check bits 、 Stop bit 、 Data bits ;
Set the default to 16 Base display ;
Clear receive buffer ( Black areas ).
(2) Make button function connection
” Scan the serial port “ Button to rescan the current serial port device , And update its status to the corresponding drop-down box ;
“ Open the serial port ” Button to issue serial port configuration and open serial port , Add open failure mode to prompt the user , Successfully added and opened, the button changes to “ Turn off the serial port ”;
" Turn off the serial port " The button will clear Serial port and close the serial port ;
“ Clear receive ” take textEdit clear fall ;
“ Save window ” Save the contents of the current receiving box to... Under the project directory txt, And clear the current receiving frame ;
“ send out ” Data processing operation will be performed and sent to the open serial port , Of course, there will be a prompt of serial port failure ;
“ Clear send ” The current send box will be cleared ;
(3) Adjust interface logic details
“ A serial port choice ”QFrame Fixed size , Does not change with the size of the interface ;
“ A serial port choice ” The overall vertical layout after the horizontal layout of the middle horizontal elements ;
“ Receiving frame ” Read only mode ;
Set up “ Receiving frame ” Style sheets , Black background , Green font ;
“ Send box ” Show me by default logo;

2.5 The underlying logic

(1) Get the current configuration function , The return value is the enumeration type , convenient “ Open the serial port ” Called when the , Take the current configuration of the check bit as an example , as follows :

enum QSerialPort::Parity MainWindow::getParity()
{
    
    QString currentParityBit = ui->checkBit_Sel->currentText();
    if (currentParityBit == "None")
        return QSerialPort::NoParity;
    else if (currentParityBit == "Odd")// Odd number 
        return QSerialPort::OddParity;
    else if (currentParityBit == "Even")// Even check 
        return QSerialPort::EvenParity;
    else
        return QSerialPort::UnknownParity;
}

(2) receive data , The serial port data buffer will send a signal when receiving data &QSerialPort::readyRead, Therefore, the user only needs to write the slot function and link it .
notice:
(2.1) For example, the other party sends 0x11、0x22、0x33、0x44、0x55, The data of , It may trigger many times ReadSerialData() call , This is not the end of the collection 5 Data , Will trigger once , But the data read away , I won't read it again next time , This can be assured ;
(2.2) Here we need to judge what is read QByteArray Of buffer Is it empty , I have encountered during debugging , Empty data , It also triggers an entry into the slot function ;
(2.3) receive ( send out ) The data type is QByteArray The type of , The receiving side needs to perform data type conversion to facilitate display processing

 str.append(QString::number((ary[i]&0xff),16));//QByteArray-->QString

(2.4) Receive operation read、readAll, And send operation write Are non blocking operations , That is, function execution , Whether or not all data is received ( send out ), Functions will immediately return , The program will continue .
(2.5) Support 16 The display of decimal system 、Ascii Display of codes ( Two types of data processing )

(3) send data
The default in accordance with the 16 Send data in hexadecimal mode , Therefore, only 16 Hexadecimal related character input , Other characters will not be allowed .

3. Code

3.1.cpp File code

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QMessageBox>
#include <QFile>
#include <QTextStream>
#include <QByteArray>
#include <QTextDecoder>
#include <QTextCodec>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    
    ui->setupUi(this);
    //QAbstractNativeEventFilter QT System event filter , For example, the serial port plug-in can identify 
    // That is, real-time detection of equipment status by means of interruption 
    Init();// Initialization function , effect : Scan the online serial port ; Fill baud rate 、 Check bit 、 Data bits 、 Stop bit widget 
    // Rescan the online serial port ( Displays the current device status )
    connect(ui->scanBtn,&QPushButton::clicked,[=](){
    
        ui->comboBox->clear();
        foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
        {
    
            ui->comboBox->addItem(info.portName());
        }
    });
    // Turn on the serial button 
    connect(ui->openBtn,&QPushButton::clicked,[=](){
    

        if(ui->openBtn->text()==" Open the serial port ")
        {
    
// qDebug()<<getBaud()<<getParity()<<getdataBits()<<getstopBits();
            mySerialPort->setPortName(ui->comboBox->currentText());
            mySerialPort->setBaudRate(getBaud());
            mySerialPort->setParity(getParity());
            mySerialPort->setDataBits(getdataBits());
            mySerialPort->setStopBits(getstopBits());
// mySerialPort->setFlowControl(QSerialPort::NoFlowControl); // TODO: FlowControl
// mySerialPort->setReadBufferSize(0); // The buffer is infinite 
            if(!(mySerialPort->open(QSerialPort::ReadWrite)))
            {
    
                // The standard dialog box prompts that opening the serial port failed 
                QMessageBox::warning(this," Warning "," Failed to open serial port ");

            }
            else
            {
    
                ui->openBtn->setText(" Turn off the serial port ");   
            }

        }
        else
        {
    
            mySerialPort->clear();
            mySerialPort->close();
            ui->openBtn->setText(" Open the serial port ");
        }
    });
    // Save button 
    connect(ui->saveBtn,&QPushButton::clicked,[=](){
    
            QFile file("UART_Rec.txt");
            file.open(QIODevice::Append);
            // Use QTextStream write file 
            QTextStream tsm(&file);
            tsm<<ui->reci_Edit->toPlainText();
            ui->reci_Edit->clear();
            file.close();
    });
    // Clear the receive button 
    connect(ui->clearRecBtn,&QPushButton::clicked,[=](){
    
        ui->reci_Edit->clear();
    });
    // Clear the send button 
    connect(ui->clearXferBtn,&QPushButton::clicked,[=](){
    
        ui->xferEdit->clear();
    });
    // Send button 
    connect(ui->xferBtn, &QPushButton::clicked, this, [=](){
    
        if(!mySerialPort->isOpen())
        {
    
            QMessageBox::information(this," Tips "," Please open the serial port first ");
        }
        else
        {
    
// // Get the send box character 
            QString str = ui->xferEdit->document()->toPlainText();
            if (str.isEmpty())
            {
    
                QMessageBox::information(this," Tips "," Please enter the sending content first ");
            }
            // Default 16 Base send , Filter useless characters   Include 0x
            else
            {
    
                char ch;
                bool flag = false;
                uint32_t i, len;
                // Get rid of useless symbols 
                str = str.replace(' ',"");
                str = str.replace(',',"");
                str = str.replace('\r',"");
                str = str.replace('\n',"");
                str = str.replace('\t',"");
                str = str.replace("0x","");
                str = str.replace("0X","");
                str = str.replace('\\',"");
                str = str.replace(':',"");
                str = str.replace('?',"");
                str = str.replace(';',"");
                // Judge the validity of data 
                for(i = 0, len = str.length(); i < len; i++)
                {
    
                    ch = str.at(i).toLatin1();
                    if (ch >= '0' && ch <= '9')
                    {
    
                        flag = false;
                    }
                    else if (ch >= 'a' && ch <= 'f')
                    {
    
                        flag = false;
                    }
                    else if (ch >= 'A' && ch <= 'F')
                    {
    
                        flag = false;
                    }
                    else
                    {
    
                        flag = true;
                    }
                }
            if(flag)
            {
    
                QMessageBox::warning(this," Warning "," The input contains illegal 16 Hexadecimal characters ");
            }
            else
            {
    
                //QString turn QByteArray
                QByteArray xferAry = str.toUtf8();
            mySerialPort->write(xferAry);
            }
            }
        }
    });

    // receive Buffer
    connect(mySerialPort,&QSerialPort::readyRead,[=](){
    
        if(ui->hex_Rtn->isChecked())
        {
    
            // With 16 Base display 
            QByteArray ary = mySerialPort->readAll();
            qDebug()<<ary;
            QString str;
            str.clear();
            for (int i = 0;i<ary.size()-2 ;i++ ) {
    
                str.append(QString::number((ary[i]&0xff),16));// take 16 Hexadecimal output as is 
// str.append(" ");
            }
            ui->reci_Edit->append(str);
// ui->reci_Edit->append("\n");
        }
        else
        {
    
            // With Ascii Code display  Ascii Code means 16 The character corresponding to base , Namely ascii One of the rules 16 Mapping between base and character 
            ui->reci_Edit->append(mySerialPort->readAll());
            ui->reci_Edit->append("\n");
        }
    });
}

MainWindow::~MainWindow()
{
    
    if(mySerialPort->isOpen())
    {
    
        mySerialPort->clear();
        mySerialPort->close();
    }
    delete mySerialPort;
    delete ui;
}

enum QSerialPort::Parity MainWindow::getParity()
{
    
    QString currentParityBit = ui->checkBit_Sel->currentText();
    if (currentParityBit == "None")
        return QSerialPort::NoParity;
    else if (currentParityBit == "Odd")// Odd number 
        return QSerialPort::OddParity;
    else if (currentParityBit == "Even")// Even check 
        return QSerialPort::EvenParity;
    else
        return QSerialPort::UnknownParity;
}

enum QSerialPort::BaudRate MainWindow::getBaud()
{
    
    bool ok;
    enum QSerialPort::BaudRate ret;
    switch (ui->baud_Sel->currentText().toLong(&ok, 10))
    {
    
        case 1200:
            ret = QSerialPort::Baud1200;
        break;
        case 2400:
            ret = QSerialPort::Baud2400;
            break;
        case 4800:
            ret = QSerialPort::Baud4800;
            break;
        case 9600:
            ret = QSerialPort::Baud9600;
            break;
        case 19200:
            ret = QSerialPort::Baud19200;
            break;
        case 38400:
            ret = QSerialPort::Baud38400;
            break;
        case 57600:
            ret = QSerialPort::Baud57600;
            break;
        case 115200:
            ret = QSerialPort::Baud115200;
            break;
        default:
            ret = QSerialPort::UnknownBaud;
            break;
    }
    return ret;
}

enum QSerialPort::StopBits MainWindow::getstopBits()
{
    
     QString currentStopBits = ui->stopBit_Sel->currentText();
     if (currentStopBits == "1")
         return QSerialPort::OneStop;
     else if (currentStopBits == "1.5")
         return QSerialPort::OneAndHalfStop;
     else if (currentStopBits == "2")
         return QSerialPort::TwoStop;
     else
         return QSerialPort::UnknownStopBits;
}

enum QSerialPort::DataBits MainWindow::getdataBits()
{
    
    QString currentDataBits = ui->dataBit_Sel->currentText();
    if(currentDataBits == "5")
        return QSerialPort::Data5;
    else if (currentDataBits == "6")
        return QSerialPort::Data6;
    else if (currentDataBits == "7")
        return QSerialPort::Data7;
    else if (currentDataBits == "8")
        return QSerialPort::Data8;
    else
        return QSerialPort::UnknownDataBits;

}

void MainWindow::Init()
{
    

    // First scan the current serial port , initialization COM Port selection component 
    QStringList myPortName;
    foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
    {
    
        myPortName << info.portName();
        qDebug()<<"serialPortName:"<<info.portName();
        qDebug() << "Description : " << info.description();
        qDebug() << "Manufacturer: " << info.manufacturer();
        qDebug() << "Serial Number: " << info.serialNumber();
        qDebug() << "System Location: " << info.systemLocation();
    }
    myPortName.sort();
    ui->comboBox->addItems(myPortName);

    // Initialize the baud rate component 
    QStringList myBaud;
    myBaud.clear();
    myBaud<<"1200"<<"2400"<<"4800"<<"9600"<<"19200"<<"38400"<<"57600"<<"115200";
    ui->baud_Sel->addItems(myBaud);
    ui->baud_Sel->setCurrentText("9600");
    // Initialize stop bit 
    QStringList mystopBits;
    mystopBits.clear();
    mystopBits<<"1"<<"1.5"<<"2";
    ui->stopBit_Sel->addItems(mystopBits);
    ui->stopBit_Sel->setCurrentText("1");
    // Initialize check bit 
    QStringList mycheckBits;
    mycheckBits.clear();
    mycheckBits<<"None"<<"Even"<<"Odd";
    ui->checkBit_Sel->addItems(mycheckBits);
    ui->checkBit_Sel->setCurrentText("None");
    // Initialize data bits 
    QStringList mydataBits;
    mydataBits.clear();
    mydataBits<<"5"<<"6"<<"7"<<"8";
    ui->dataBit_Sel->addItems(mydataBits);
    ui->dataBit_Sel->setCurrentText("8");
    
    ui->hex_Rtn->setChecked(true);// The default setting is 16 Base display 
    ui->reci_Edit->clear();
}

3.2.h Code

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QtSerialPort/QSerialPortInfo>
#include <QtSerialPort/QSerialPort>

QT_BEGIN_NAMESPACE
namespace Ui {
     class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    enum QSerialPort::Parity getParity();
    enum QSerialPort::BaudRate getBaud();
    enum QSerialPort::StopBits getstopBits();
    enum QSerialPort::DataBits getdataBits();
    void Init();

     // Create a serial port object 
    QSerialPort *mySerialPort = new QSerialPort();

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

4. effect

Use virtual serial port software VSPD Virtual serial port , Use mature software XCOM V2.0( Punctual atomic serial port debugging assistant ) Communicate with your own software , Can be seen clearly , Software receiving and sending are normal .VSPD For software acquisition and installation, please see Tool class – Virtual serial tools

 Insert picture description here

5. reflection

Two ideas ,1.USB It belongs to hot plug device , The system can dynamically detect the insertion and disconnection of equipment , So how to make your software dynamically view the connection status of serial port devices ? actually ,Qt Provides “ interrupt ” Interface , It can be upgraded ;
2. Now it only supports 16 Base send , Support 16 Base number 、ascii Code reception , So can we consider using serial port to transmit Chinese characters ? actually ,Qt Support multiple character sets , Try it .

原网站

版权声明
本文为[Morning and evening rain]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/172/202206211658130130.html