QT实现串口调试功能(QSerialPort类)

1、简介

     本博文主要是介绍如何使用QT的串口类(QSerialPort)来实现串口的开发,使用这个类来实现串口的基本功能,比如如何查询本机可用串口(com),打开串口、设置串口波特率、设置数据位、设置校验位、停止位等窗口属性。还实现了十六进制收发显示数据,经过测试,本工程代码可以在WIN7+QT 或者 Ubuntu + QT环境下正常运行。

2、主要使用QSerialPort类的借口

(1)、void readyRead():串口信号,只要串口接收到数据,就会发送(emit)该信号,我们要用信号槽函数连接该信号以便               接收串口的所有数据。

(2)、QByteArray readAll():读取串口的所有数据,返回值QByteArray。

(3)、qint64 write(const QByteArray &data):发送数据到串口,发送成功,返回发送的字节数。

3、工程封装的主要接口

(1)、ShowMsg(int iTime, QString sMsg):显示提示消息函数,主要显示操作串口的提示消息,比如打开串口成功与否。

(2)、on_tbOpen_clicked():打开串口,本设置串口波特率等属性,并连接信号槽。

(3)、QString与QByteArray十六进制间的转换。

4、软件界面布局如下

QT实现串口调试功能(QSerialPort类)_第1张图片

5、代码演示

(1)、MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include
#include
#include
#include

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    void ShowMsg(int iTime, QString sMsg);
    void msleep(int ms);

private slots:
    void onReadData();

private slots:
    void on_tbClearRecv_clicked();
    void on_tbClearSend_clicked();
    void on_tbOpen_clicked();
    void on_tbExit_clicked();    

    void on_cbHexSHow_clicked(bool checked);
    void on_tbSendData_clicked();

protected:
    void timerEvent(QTimerEvent* event);

private:
    Ui::MainWindow *ui;

    int m_iTimerID;
    QSerialPort *m_pSerial;
};

#endif // MAINWINDOW_H

(2)、MainWindow.cpp

#include "Mainwindow.h"
#include "ui_Mainwindow.h"

#include
#include
#include
#include
#include

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    m_iTimerID = 0;
    m_pSerial = NULL;

    //查找可用的串口
    foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
    {
        QSerialPort pSerial;
        pSerial.setPort(info);

        //尝试打开串口,如果能打开,说明串口可用,否则串口不可用
        if(pSerial.open(QIODevice::ReadWrite))
        {
            //把可用的串口添加到界面控件
            ui->tbPortBox->addItem(pSerial.portName());
            pSerial.close();
        }
    }

    //波特率默认115200,数据位默认7
    ui->tbBaudBox->setCurrentIndex(7);
    ui->tbBitNumBox->setCurrentIndex(3);
}

MainWindow::~MainWindow()
{
    //关闭显示消息定时器
    killTimer(m_iTimerID);

    //关闭串口 释放资源
    if (m_pSerial && m_pSerial->isOpen()) m_pSerial->close();

    delete ui;
}

//显示信息
void MainWindow::ShowMsg(int iTime, QString sMsg)
{
    if (m_iTimerID) killTimer(m_iTimerID);
    ui->labelMsg->show();
    ui->labelMsg->setText(sMsg);
    m_iTimerID = this->startTimer(iTime);
}

//清空接受窗口
void MainWindow::on_tbClearRecv_clicked()
{
    ui->teRecvData->clear();
}

//清空接收窗口
void MainWindow::on_tbClearSend_clicked()
{
    ui->teSendData->clear();
}

//打开串口100
void MainWindow::on_tbOpen_clicked()
{
    if(ui->tbOpen->text()==tr("打开串口"))
    {
        if (m_pSerial)
        {
            delete m_pSerial;
            m_pSerial = NULL;
        }
        m_pSerial = new QSerialPort();

        //设置串口名
        QString sComName = ui->tbPortBox->currentText();
        m_pSerial->setPortName(sComName);

        //打开串口
        bool b = m_pSerial->open(QIODevice::ReadWrite);
        ShowMsg(4500, b ? tr("打开串口成功") : tr("打开串口失败"));

        //设置波特率
        int iBaudRate = ui->tbBaudBox->currentText().toInt();
        m_pSerial->setBaudRate(iBaudRate);

        //设置数据位数
        int iDataType = ui->tbBitNumBox->currentIndex();
        switch(iDataType)
        {
        case 0: m_pSerial->setDataBits(QSerialPort::Data5); break;
        case 1: m_pSerial->setDataBits(QSerialPort::Data6); break;
        case 2: m_pSerial->setDataBits(QSerialPort::Data7); break;
        case 3: m_pSerial->setDataBits(QSerialPort::Data8); break;
        default: break;
        }

        //设置奇偶校验
        switch(ui->tbParityBox->currentIndex())
        {
        case 0: m_pSerial->setParity(QSerialPort::NoParity); break;
        case 1: m_pSerial->setParity(QSerialPort::OddParity); break;
        case 2: m_pSerial->setParity(QSerialPort::EvenParity); break;
        default: break;
        }

        //设置停止位
        int iStopType = ui->tbStopBox->currentIndex();
        switch(iStopType)
        {
        case 0: m_pSerial->setStopBits(QSerialPort::OneStop); break;
        case 1: m_pSerial->setStopBits(QSerialPort::TwoStop); break;
        default: break;
        }

        //设置流控制
        m_pSerial->setFlowControl(QSerialPort::NoFlowControl);

        //关闭设置菜单使能
        ui->tbPortBox->setEnabled(false);
        ui->tbBaudBox->setEnabled(false);
        ui->tbBitNumBox->setEnabled(false);
        ui->tbParityBox->setEnabled(false);
        ui->tbStopBox->setEnabled(false);
        ui->tbOpen->setText(tr("关闭串口"));

        //连接信号槽,接收串口发送过来的所有消息
        connect(m_pSerial, SIGNAL(readyRead()), this, SLOT(onReadData()));
    }
    else
    {
        //关闭串口
        if (m_pSerial)
        {
            m_pSerial->clear();
            m_pSerial->close();
            m_pSerial->deleteLater();
            delete m_pSerial;
            m_pSerial = NULL;
        }

        //恢复设置使能
        ui->tbPortBox->setEnabled(true);
        ui->tbBaudBox->setEnabled(true);
        ui->tbBitNumBox->setEnabled(true);
        ui->tbParityBox->setEnabled(true);
        ui->tbStopBox->setEnabled(true);
        ui->tbOpen->setText(tr("打开串口"));
        ShowMsg(4500, "串口已关闭");
    }
}

//退出程序
void MainWindow::on_tbExit_clicked()
{
    //退出程序,关闭串口,释放资源
    if (m_pSerial && m_pSerial->isOpen()) m_pSerial->close();

    this->close();
}

//定时器时间出发函数
void MainWindow::timerEvent(QTimerEvent *event)
{
    if (event->timerId() == m_iTimerID)
    {
        //时间到隐藏显示消息控件
        killTimer(m_iTimerID);
        m_iTimerID = 0;
        ui->labelMsg->clear();
        ui->labelMsg->hide();
    }
}

//休眠函数
void MainWindow::msleep(int ms)
{
    QTime tm;
    tm.restart();
    while (tm.elapsed() < ms)
    {
        QCoreApplication::processEvents();
    }
}

//接收串口的所有数据
void MainWindow::onReadData()
{
    if (m_pSerial == NULL) return;

    //读取串口的所有数据
    QByteArray buf = m_pSerial->readAll();

    if (ui->cbHexSHow->isChecked())
    {
        //十六进制显示
        ui->teRecvData->append(QString(buf.toHex()));
    }
    else
    {
        //原样显示
        ui->teRecvData->append(QString(buf));
    }
}

//十六进制显示
void MainWindow::on_cbHexSHow_clicked(bool checked)
{
    if (checked)
    {
        //把QString转成十六进制的QByteArray
        QByteArray ba = ui->teRecvData->toPlainText().toLocal8Bit();
        ui->teRecvData->clear();

        //显示到界面
        ui->teRecvData->append(QString(ba.toHex()));
    }
    else
    {
        QString sText = ui->teRecvData->toPlainText();
        ui->teRecvData->clear();

        //十六进制的QString转QString
        QByteArray ba = QByteArray::fromHex(sText.toLocal8Bit());
        ui->teRecvData->append(QString(ba.data()));
    }
}

//发送数据
void MainWindow::on_tbSendData_clicked()
{
    if (m_pSerial == NULL) return;

    //把发送的所有数据读取下来
    QString sText = ui->teSendData->toPlainText();
    if (sText.isEmpty()) return;

    if (ui->cbHexSend->isChecked())
    {
        //按十六进制发送
        m_pSerial->write(sText.toLocal8Bit().toHex());
    }
    else
    {
        //原样发送
        m_pSerial->write(sText.toLocal8Bit());
    }

    //清空发送区
    ui->teSendData->clear();
}

6、测试结果

QT实现串口调试功能(QSerialPort类)_第2张图片

你可能感兴趣的:(QT)