Qt實現高精度定時器

一般而言,Qt有兩種使用定時器的方式, QObject和QTimer,對於第一種需要重寫timerEvent事件來實現,第二種需要聲明一個QTimer的對象或指針,用QTimer::timeout()信號連接槽函數,設置定時器類型mTimer.setTimerType(Qt::PreciseTimer);

第一種即使高精度的定時器,保持毫秒級別;第二種粗計時器盡量將精度保持在所需間隔的5%以內;第三種非常粗糙的計時器隻能保持完整的秒精度.

#ifndef BACKENDPROIXY_H
#define BACKENDPROIXY_H
 
#include <QObject>
#include <QTimer>
#include <QTime>
 
class BackendProxy : public QObject
{
    Q_OBJECT
public:
    explicit BackendProxy(QObject *parent = nullptr);
 
signals:
private slots:
    void onTimeOut();
private:
    QTimer mTimer;
    QTime lastTime;
 
};
 
#endif // BACKENDPROIXY_H
#include "backendproixy.h"
 
#include <QDebug>
 
BackendProxy::BackendProxy(QObject *parent) : QObject(parent)
{
    connect(&mTimer,&QTimer::timeout,this,&BackendProxy::onTimeOut);
    mTimer.setTimerType(Qt::PreciseTimer);
    mTimer.start(50);
}
 
 
void BackendProxy::onTimeOut()
{
    QTime currentTime;
    int elapsed = 0;
    if(lastTime == QTime()){
        lastTime = QTime::currentTime();
    }else{
        currentTime = QTime::currentTime();
        elapsed = lastTime.msecsTo(currentTime);
        lastTime = QTime::currentTime();
    }
    qDebug()<<"Run.elapsed ="<<elapsed<<"ms";
}

下面分別展示三種類型的時間間隔:

Qt::PreciseTimer:

Qt::CoarseTimer:

Qt::VeryCoarseTimer:

顯而易見,第一種的精度最高,但偶爾也會超過20ms,對於一些實時性較高的通訊來說,還是達不到要求.使用線程加延時能達到最多正負1ms的誤差,一下輸出我使用的是10ms一個周期:

現在也貼上代碼:

#ifndef PERFORMANCEFREQUENCY_H
#define PERFORMANCEFREQUENCY_H
 
#include<QThread>
#include<QDebug>
#include<QUdpSocket>
#include <QHostAddress>
 
 
#define SEND_TIME 10
 
class PerformanceFrequency : public QThread
{
    Q_OBJECT
public:
    explicit PerformanceFrequency(QObject *parent = nullptr);
    void setThreadRunning(bool start){bRunning = start;}
    void appendByte(QByteArray array);
    void removeOneByte(QByteArray array);
signals:
    void sendJaguarJointControl(QByteArray ba);
    void heartTime(int time);
protected:
    void run() override;
private:
    QList<QByteArray> listByte;
    bool bRunning = true;
 
};
 
#endif // PERFORMANCEFREQUENCY_H
#include "performancefrequency.h"
#include <QTime>
 
#include <QMutex>
#include <QMutexLocker>
 
PerformanceFrequency::PerformanceFrequency(QObject *parent)
    : QThread(parent)
{
    QByteArray heart;
    heart[0] = 0xf0;
    heart[1] = heart[2] = heart[3] = heart[4] = heart[5] = heart[6] = heart[7] =  0;
    listByte.append(heart);
}
 
void PerformanceFrequency::run()
{
    while(bRunning){
        QTime startTime = QTime::currentTime();
        msleep(SEND_TIME);
        for(int i = 0;i < listByte.size();i++){
            emit sendJaguarJointControl(listByte.at(i));
        }
 
        QTime stopTime = QTime::currentTime();
        int elapsed = startTime.msecsTo(stopTime);
        emit heartTime(elapsed);
        qDebug()<<"Run.elapsed ="<<elapsed<<"ms";
    }
}
 
void PerformanceFrequency::appendByte(QByteArray array)
{
    static QMutex mutex;
    QMutexLocker locker(&mutex);
    listByte.append(array);
}
void PerformanceFrequency::removeOneByte(QByteArray array)
{
    static QMutex mutex;
    QMutexLocker locker(&mutex);
    listByte.removeOne(array);
}

以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。

推薦閱讀: