Qt qextserial進行串口數據採集,qcustomplot進行繪圖,曲線實時顯示橫縱座標輔助線

Qt qextserial進行串口數據採集,qcustomplot進行繪圖,曲線實時顯示橫縱座標輔助線

目的、要求:

A.讀取RS422接口接收到的全部數據;

1.通過接口讀取板卡採集的數據,採用多線程,讀取數據和解析數據在主線程,繪製曲線在另一個新的線程。COM和API接口見附件1.板卡用戶手冊。

2.根據接收到的數據,需要先判定是返參幀A還是返參幀B,每一幀具有27個字節,每幀依據“幀頭”和“校驗和”來判定。

需要注意:

a)數據流起始位置並不一定是“幀頭”。

b)數據流中可能存在無效的數據包,需要注意判定邏輯,以免丟失有效數據。

B.能夠依據協議對數據進行解析並存儲;

1.要求對返參幀A和返參幀B數據分別解析,詳細的解析與處理要求見附件2。附件2中需要用到的解析協議見附件3。

2.將接收到的返參幀A和返參幀B分別存儲在文檔不同的sheet中,文檔格式爲".xlsx",允許用戶在軟件界面上以點擊按鈕的形式選擇數據存儲開始/結束,允許用戶選擇設置路徑。

3.存儲內容包括附件2表中全部解析內容,每一項解析內容對應存儲在文檔中一列,存儲數據爲解析後未經數據處理的數據。

C.對解析後的一些數據,以曲線的形式顯示。

1.軟件需對返參幀A和返參幀B的部分解析內容進行實時曲線繪製,需要繪製曲線的參數見附件4。共15個曲線圖。

2.通過“選項卡”的形式將不同類型曲線放置在不同選項卡頁面中。

3.要求曲線能根據接收解析後的數據點進行動態實時更新,從右向左,橫座標代表點的個數,曲線對應的橫座標刻度要一同向左更新移動。

4.要求曲線窗口有圖標題,有橫縱座標標題;如果一個曲線窗口中有多條曲線,要求用不同顏色區分,對不同曲線有標註;用戶可選擇僅顯示其中某一條或某兩條曲線;

5.曲線要求正常顯示爲1000個數據點,緩存區要求存180000個數據點,可在曲線窗口上左右拖拽以查看180000中的各個1000個數據點的顯示區間,超出180000個數據點緩存區後,每進入一個新的數據點,則順次清除一個原數據點。曲線橫、縱座標範圍允許用戶調整,可進行2、4、6、8倍的4檔放大麴線局部判讀。

6.鼠標移動到曲線上的數據點上時,要求有指向橫、縱座標的輔助線。

簡介:

考慮到這個要移植到硬件上,到時候交叉編譯後的Qt環境需要串口模塊的支持。所以選用了第三方的chua串口通訊模塊qextserial進行串口通訊。繪圖使用的第三方的qcustomplot。串口模塊放到線程裏,數據處理和繪圖部分放到了主線程。這個地方主要麻煩的是對通訊幀的解析。首先分爲A B兩種mo's模式,每個字節對應的有不同的含義。有些字節的某幾位對應的不同的含義。剩下的就是數據的輔助線問題了。輔助線繼承了QCustomPlot,然後重寫了鼠標事件和其他的一些事件。

效果:

代碼:

#ifndef MHCUSTOMPLOT_H
#define MHCUSTOMPLOT_H

#include "mhtracer.h"
#include "qcustomplot.h"
#include <QObject>
#include <QList>

class MhCustomPlot : public QCustomPlot
{
    Q_OBJECT
public:
    MhCustomPlot(QWidget *parent = 0);

protected:
    virtual void mouseMoveEvent(QMouseEvent *event);
    virtual void enterEvent(QEvent *event);
    virtual void leaveEvent(QEvent *event);
    //virtual void mouseDoubleClickEvent(QMouseEvent *event);
//signals:
    //void legendDoubleClickChilden(QCPLegend *legend,  QCPAbstractLegendItem *item, QMouseEvent *event);
public:
    //設置是否顯示鼠標追蹤器
    //是否顯示
    void showTracer(bool show);
    // 是否顯示鼠標追蹤器
    bool isShowTracer(){return m_isShowTracer;}

private:
    bool m_isShowTracer;//是否顯示追蹤器(鼠標在圖中移動,顯示對應的值)
    MhTracer *m_xTracer;//x軸
    MhTracer *m_yTracer;//y軸
    QList<MhTracer *> m_dataTracers;//
    MhTraceLine  *m_lineTracer;//直線
};

#endif // MHCUSTOMPLOT_H
#include "mhcustomplot.h"

MhCustomPlot::MhCustomPlot(QWidget *parent)
    :QCustomPlot(parent)
    ,m_isShowTracer(false)
    ,m_xTracer(Q_NULLPTR)
    ,m_yTracer(Q_NULLPTR)
    ,m_dataTracers(QList<MhTracer *>())
    ,m_lineTracer(Q_NULLPTR)
{

}
//設置是否顯示鼠標追蹤器
//是否顯示
void MhCustomPlot::showTracer(bool show)
{
    m_isShowTracer = show;
    if(m_xTracer)
        m_xTracer->setVisible(m_isShowTracer);
    ///
    if(m_yTracer)
    {
        m_yTracer->setVisible(m_isShowTracer);
    }
    foreach (MhTracer *tracer, m_dataTracers)
    {
        if(tracer)
            tracer->setVisible(m_isShowTracer);
    }
    if(m_lineTracer)
        m_lineTracer->setVisible(m_isShowTracer);
}

void MhCustomPlot::mouseMoveEvent(QMouseEvent *event)
{
    QCustomPlot::mouseMoveEvent(event);

    if(m_isShowTracer)
    {
        //當前鼠標位置(像素座標)
        int x_pos = event->pos().x();
        int y_pos = event->pos().y();

        //qDebug() << "x_pos:" << x_pos << "y_pos:" << y_pos;

        //像素座標轉成實際的x,y軸的座標
        float x_val = this->xAxis->pixelToCoord(x_pos);
        float y_val = this->yAxis->pixelToCoord(y_pos);

        if(Q_NULLPTR == m_xTracer)
            m_xTracer = new MhTracer(this, MhTracer::XAxisTracer);//x軸
        m_xTracer->updatePosition(x_val, y_val);

        if(Q_NULLPTR == m_yTracer)
            m_yTracer = new MhTracer(this, MhTracer::YAxisTracer);//y軸
        m_yTracer->updatePosition(x_val, y_val);

        int nTracerCount = m_dataTracers.count();
        int nGraphCount = graphCount();
        if(nTracerCount < nGraphCount)
        {
            for(int i = nTracerCount; i < nGraphCount; ++i)
            {
                MhTracer *tracer = new MhTracer(this, MhTracer::DataTracer);
                m_dataTracers.append(tracer);
            }
        }
        else if(nTracerCount > nGraphCount)
        {
            for(int i = nGraphCount; i < nTracerCount; ++i)
            {
                MhTracer *tracer = m_dataTracers[i];
                if(tracer)
                {
                    tracer->setVisible(false);
                }
            }
        }
        for (int i = 0; i < nGraphCount; ++i)
        {
            MhTracer *tracer = m_dataTracers[i];
            if(!tracer)
                tracer = new MhTracer(this, MhTracer::DataTracer);
            tracer->setVisible(true);
            tracer->setPen(this->graph(i)->pen());
            tracer->setBrush(Qt::NoBrush);
            tracer->setLabelPen(this->graph(i)->pen());
            auto iter = this->graph(i)->data()->findBegin(x_val);
            double value = iter->mainValue();
//            double value = this->graph(i)->data()->findBegin(x_val)->value;
            tracer->updatePosition(x_val, value);
        }

        if(Q_NULLPTR == m_lineTracer)
            m_lineTracer = new MhTraceLine(this,MhTraceLine::Both);//直線
        m_lineTracer->updatePosition(x_val, y_val);

        this->replot(QCustomPlot::rpQueuedReplot);//曲線重繪
    }
}

void MhCustomPlot::enterEvent(QEvent *event)
{
    //QCustomPlot::enterEvent(event);
    //qDebug() << "鼠標進入";
    m_isShowTracer = true;
    if(m_xTracer)
        m_xTracer->setVisible(m_isShowTracer);
    if(m_yTracer)
    {
        m_yTracer->setVisible(m_isShowTracer);
    }
    foreach (MhTracer *tracer, m_dataTracers)
    {
        if(tracer)
            tracer->setVisible(m_isShowTracer);

    }
    if(m_lineTracer)
        m_lineTracer->setVisible(m_isShowTracer);
    this->replot(QCustomPlot::rpQueuedReplot);
}

void MhCustomPlot::leaveEvent(QEvent *event)
{
    //QCustomPlot::leaveEvent(event);
    //qDebug() << "鼠標離開";
    m_isShowTracer = false;
    if(m_xTracer)
        m_xTracer->setVisible(m_isShowTracer);
    if(m_yTracer)
    {
        m_yTracer->setVisible(m_isShowTracer);
    }
    foreach (MhTracer *tracer, m_dataTracers)
    {
        if(tracer)
            tracer->setVisible(m_isShowTracer);
    }
    if(m_lineTracer)
        m_lineTracer->setVisible(m_isShowTracer);
    this->replot(QCustomPlot::rpQueuedReplot);
}

//void MhCustomPlot::mouseDoubleClickEvent(QMouseEvent *event)
//{
//    QCustomPlot::mouseDoubleClickEvent(event);
//}

 

exe地址(百度網盤鏈接):

鏈接:https://pan.baidu.com/s/1YeYbY32FM1Ol1FKvdLUUJA 
提取碼:tr0d 

QQ:921673516  QQ羣:511450936  郵箱:[email protected]

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