欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Qt:采用第三方串口类CSerialPort V4.0.3开发的串口助手,支持高波特率

程序员文章站 2022-07-13 13:34:36
...

首先感谢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
效果图:

Qt:采用第三方串口类CSerialPort V4.0.3开发的串口助手,支持高波特率
下面时代码的大体结构:
Qt:采用第三方串口类CSerialPort V4.0.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
大佬的开源代码,非常实用,倾力推荐!

需要项目源码请点击此处
有问题联系:aaa@qq.com