Qt:採用第三方串口類CSerialPort V4.0.3開發的串口助手,支持高波特率

首先感謝itas109大佬的開源代碼,用起來真的簡單方便,且經過多年修改完善代碼整體框架比較健全,很多大公司都在使用這個串口類。

初次使用這個串口類是在MFC下開發串口通訊時使用的(代碼鏈接:使用CSerialPort開源類在MFC下開發的串口助手),當時就感覺特別的簡單方便,之後因爲項目需要就在Qt下開始使用了,剛開始使用了Qt自帶的串口類,但是感覺操作繁瑣,且不支持高波特率,後來又還了Qt的第三方串口類qextserialport類,但是因爲缺乏維護且問題較多,所以最後還是找了itas109大佬的開源串口類,結果顯而易見,在Qt環境下的使用還是一如既往的方便簡單,且本人實測,921600波特率下,20ms週期發送接收數據穩定!

重點來了:itas109大佬博客:http://blog.csdn.net/itas109
QQ羣,平時遇到的問題或者串口使用想到的新需求都可以在羣裏提:129518033
Git:https://github.com/itas109/CSerialPort裏邊有最新版本的發佈以及以往個版本的更新說明;
環境:QT5.6.3
效果圖:

這是軟件界面,有定時發送,十六進制發送接收以及字符發生接收的功能
下面時代碼的大體結構:
大體結構

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTimer>
#include "SerialPort.h"

using namespace std;
using namespace itas109;

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow, public has_slots<>
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    //轉16進制
    QByteArray QString2Hex(QString str);
    char ConvertHexChar(char ch);
    QTimer *m_time;

private slots:
    void OnReceive();

    void OnUpdateReceive(QString str);

    void on_pushButtonOpen_clicked();

    void on_pushButtonSend_clicked();

    void on_pushButtonClear_clicked();

    void on_checkBoxSync_stateChanged(int arg1);

    void on_pushButtonReadSync_clicked();

    void on_checkBoxSync_clicked(bool checked);

    void time_send();

signals:
    void emitUpdateReceive(QString str);

private:
    Ui::MainWindow *ui;

    CSerialPort m_SerialPort;

    int tx;
    int rx;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "SerialPortInfo.h"
#include <QDebug>
#include <QScrollBar>
#include <QMessageBox>
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    ui->spinBox->setMaximum(5000);
    ui->spinBox->setMinimum(5);
    connect(this,&MainWindow::emitUpdateReceive,this,&MainWindow::OnUpdateReceive,Qt::QueuedConnection);

    //hide pushButtonReadSync
    ui->pushButtonReadSync->hide();//隱藏這個控件

    //ui
    ui->pushButtonOpen->setText(tr("open"));
    rx = 0;
    tx = 0;
    setWindowTitle(this->windowTitle() + "串口助手" +QString::fromStdString(m_SerialPort.getVersion()));

    //自動獲取端口
    vector<SerialPortInfo> portNameList = CSerialPortInfo::availablePortInfos();
    for (int i = 0; i < portNameList.size(); i++)
    {
        ui->comboBoxPortName->insertItem(i,QString::fromLocal8Bit(portNameList[i].portName.c_str()));
    }

    //初始化
    m_SerialPort.readReady.connect(this, &MainWindow::OnReceive);
    ui->comboBoxBaudrate->setCurrentText("115200");
    ui->comboBoxDataBit->setCurrentText("8");
    //qDebug() << QString::fromStdString(m_SerialPort.getVersion());
}
MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::OnReceive()
{
    int iRet = -1;
    char * str = NULL;
    str = new char[512];
    iRet = m_SerialPort.readAllData(str);

    //qDebug() << "read length : " << iRet;
    if(iRet != -1)
    {
        // TODO: 中文需要由兩個字符拼接,否則顯示爲空""
        QString m_str = QString::fromLocal8Bit(str,iRet);
        //qDebug() << "receive : " << m_str;
        emit emitUpdateReceive(m_str);//發出信號
	}
    else
    {

    }
    delete str;
    str = NULL;
}
void MainWindow::OnUpdateReceive(QString str)//顯示數據
{
    rx += str.length();
    ui->labelRXValue->setText(QString::number(rx));

    //追加文本
    if(ui->checkBox->checkState()==Qt::Checked)//十六進制顯示
    {
        QByteArray temp=str.toLatin1();
        QString str3 = temp.toHex().data();//以十六進制顯示
        QString strDis;
        for(int i = 0;i<str3.length();i+=2)//填加空格
        {
               QString st = str3.mid (i,2);
               strDis += st;
               strDis += " ";
        }
        ui->plainTextEditReceive->moveCursor (QTextCursor::End);
        ui->plainTextEditReceive->insertPlainText(strDis);
    }
    else
    {
        ui->plainTextEditReceive->moveCursor (QTextCursor::End);
        ui->plainTextEditReceive->insertPlainText(str);
    }
}
void MainWindow::on_pushButtonOpen_clicked()//打開串口
{
    if(ui->pushButtonOpen->text() == tr("open"))
    {
        if(ui->comboBoxPortName->count() > 0)//檢測到端口
        {
            //初始化串口
            m_SerialPort.init(ui->comboBoxPortName->currentText().toStdString(),
                              ui->comboBoxBaudrate->currentText().toInt(),
                              itas109::Parity(ui->comboBoxParity->currentIndex()),
                              itas109::DataBits(ui->comboBoxDataBit->currentText().toInt()),
                              itas109::StopBits(ui->comboBoxStopBit->currentIndex()));

            //打開串口
            if(m_SerialPort.open())
            {
                ui->pushButtonOpen->setText(tr("close"));
            }
            else
            {
                QMessageBox::information(NULL,tr("information"),tr("open port error"));
                ui->pushButtonOpen->setText(tr("open"));
                //qDebug()<< m_SerialPort.getLastError();
            }
        }
        else
        {
            QMessageBox::information(NULL,tr("information"),tr("This Computer no avaiable port"));
            //qDebug()<< "This Computer no avaiable port";
        }
    }
    else
    {
        m_SerialPort.close();
        ui->pushButtonOpen->setText(tr("open"));
    }
}
void MainWindow::on_pushButtonSend_clicked()//發送數據
{
    if(m_SerialPort.isOpened())
    {
        if(ui->checkBox_3->checkState()==Qt::Checked)//定時發送
        {
            int timecount=ui->spinBox->value();//定時器發送的週期
            m_time=new QTimer(this);
            connect(m_time,&QTimer::timeout,this,&MainWindow::time_send);
            m_time->start(timecount);
        }
        else
        {
            if(ui->checkBox_2->checkState()==Qt::Checked)//十六進制發
            {
                QByteArray m_senddata=QString2Hex(ui->plainTextEditSend->toPlainText());
                const char *s = m_senddata.constData();
                //支持中文並獲取正確的長度
                m_SerialPort.writeData(s,m_senddata.length());
                tx+=m_senddata.length();
                ui->labelTXValue->setText(QString::number(tx));
            }
            else
            {
                QString sendStr = ui->plainTextEditSend->toPlainText();

                QByteArray ba = sendStr.toLocal8Bit();
                const char *s = ba.constData();

                //支持中文並獲取正確的長度
                m_SerialPort.writeData(s,ba.length());
                tx += sendStr.length();
                ui->labelTXValue->setText(QString::number(tx));
            }
        }
    }
    else
    {
        QMessageBox::information(NULL,tr("information"),tr("please open serial port first"));
        //qDebug() << tr("please open serial port first");
    }
}
void MainWindow::time_send()//定時發送
{
    if(ui->checkBox_3->checkState()==Qt::Checked)//定時發送
    {
        if(ui->checkBox_2->checkState()==Qt::Checked)//十六進制發
        {
            QByteArray m_senddata=QString2Hex(ui->plainTextEditSend->toPlainText());
            const char *s = m_senddata.constData();
            //支持中文並獲取正確的長度
            m_SerialPort.writeData(s,m_senddata.length());
            tx+=m_senddata.length();
            ui->labelTXValue->setText(QString::number(tx));
        }
        else
        {
            QString sendStr = ui->plainTextEditSend->toPlainText();
            QByteArray ba = sendStr.toLocal8Bit();
            const char *s = ba.constData();
            //支持中文並獲取正確的長度
            m_SerialPort.writeData(s,ba.length());
            tx += sendStr.length();
            ui->labelTXValue->setText(QString::number(tx));
        }
    }
    else
    {
        m_time->stop();
    }
}
QByteArray MainWindow::QString2Hex(QString str)
{
    QByteArray senddata;
    int hexdata,lowhexdata;
    int hexdatalen = 0;
    int len = str.length();
    senddata.resize(len/2);
    char lstr,hstr;
    for(int i=0; i<len; )
    {
        hstr=str[i].toLatin1();
        if(hstr == ' ')
        {
            i++;
            continue;
        }
        i++;
        if(i >= len)
            break;
        lstr = str[i].toLatin1();
        hexdata = ConvertHexChar(hstr);
        lowhexdata = ConvertHexChar(lstr);
        if((hexdata == 16) || (lowhexdata == 16))
            break;
        else
            hexdata = hexdata*16+lowhexdata;
        i++;
        senddata[hexdatalen] = (char)hexdata;
        hexdatalen++;
    }
    senddata.resize(hexdatalen);
    return senddata;
}
char MainWindow::ConvertHexChar(char ch)
{
    if((ch >= '0') && (ch <= '9'))
        return ch-0x30;
    else if((ch >= 'A') && (ch <= 'F'))
        return ch-'A'+10;
    else if((ch >= 'a') && (ch <= 'f'))
        return ch-'a'+10;
    else return (-1);
}
void MainWindow::on_pushButtonClear_clicked()//清空
{
    tx = 0;
    rx = 0;

    ui->labelTXValue->setText(QString::number(tx));
    ui->labelRXValue->setText(QString::number(rx));
}

void MainWindow::on_checkBoxSync_stateChanged(int arg1)//狀態改變選擇框
{
    if(arg1 == 0)
    {
        m_SerialPort.close();
    }
    else
    {
        m_SerialPort.close();
    }
}

void MainWindow::on_pushButtonReadSync_clicked()//SYNC按鍵
{
    OnReceive();
}

void MainWindow::on_checkBoxSync_clicked(bool checked)//選擇框選擇
{
    //AsynchronousOperate
    if(checked)
    {
        m_SerialPort.setOperateMode(itas109::SynchronousOperate);

        ui->pushButtonReadSync->show();
    }
    else
    {
        m_SerialPort.setOperateMode(itas109::AsynchronousOperate);

        ui->pushButtonReadSync->hide();
    }

}

基本上整個項目的代碼都在這裏了,圖片裏的源碼部分大家可以在我文章開頭處的Git鏈接出進行下載,再次感謝itas109
大佬的開源代碼,非常實用,傾力推薦!

需要項目源碼請點擊此處
有問題聯繫:[email protected]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章