打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Windows精准计时&精准Timer
以前做上层程序的时候,需要计时的时候就GetTickCount()获取当前ms来做个减法,如果有Timer需求,那肯定直接SetTimer,OnTimer,KillTimer三件套。最近遇到了一个要求发送频率50Hz,直接SetTimer将间隔设置为20,结果发现数据间隔差的离谱。查了一下,GetTickCount和Timer都是基于Windows消息循环,最小单元为55ms左右。如果想实现更高的精确度:
精确获取时间
QueryPerformanceFrequency() - 基本介绍
类型:Win32API
原型:BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);
作用:返回硬件支持的高精度计数器的频率。
返回值:非零,硬件支持高精度计数器;零,硬件不支持,读取失败。
QueryPerformanceFrequency() - 技术特点
供WIN9X使用的高精度定时器:QueryPerformanceFrequency()和QueryPerformanceCounter(),要求计算机从硬件上支持高精度定时器。需包含windows.h头文件。
函数的原形是:
BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);
BOOL QueryPerformanceCounter (LARGE_INTEGER *lpCount);
数据类型LARGEINTEGER既可以是一个作为8字节长的整数,也可以是作为两个4字节长的整数的联合结构,其具体用法根据编译器是否支持64位而定。该类型的定义如下:
typeef union _ LARGE_INTEGER
{
struct
{
DWORD LowPart;
LONG HighPart;
};
LONGLONG QuadPart;
} LARGE_INTEGER;
在定时前应该先调用QueryPerformanceFrequency()函数获得机器内部计时器的时钟频率。接着在需要严格计时的事件发生前和发生之后分别调用QueryPerformanceCounter(),利用两次获得的计数之差和时钟频率,就可以计算出事件经历的精确时间。
测试Sleep的精确时间:
[cpp]
#include <stdio.h>
#include <windows.h>
void main()
{
LARGE_INTEGER nFreq;
LARGE_INTEGER nBeginTime;
LARGE_INTEGER nEndTime;
double time;
QueryPerformanceFrequency(&nFreq);
QueryPerformanceCounter(&nBeginTime);
Sleep(1000);
QueryPerformanceCounter(&nEndTime);
time=(double)(nEndTime.QuadPart-nBeginTime.QuadPart)/(double)nFreq.QuadPart;
printf("%f\n",time);
Sleep(1000);
system("Pause");
}
结果为
0.999982
1.000088
1.000200
单位为妙,乘1000000即为微秒
------------------------------------------------------------------------
对于精准Timer,微软提供的多媒体库里面有如下的函数:
MMRESULT timeSetEvent( UINT uDelay,
UINT uResolution,
LPTIMECALLBACK lpTimeProc,
WORD dwUser,
UINT fuEvent )
uDelay:以毫秒指定事件的周期。
Uresolution:以毫秒指定延时的精度,数值越小定时器事件分辨率越高。缺省值为1ms。
LpTimeProc:指向一个回调函数。
DwUser:存放用户提供的回调数据。
FuEvent:指定定时器事件类型:
TIME_ONESHOT:uDelay毫秒后只产生一次事件
TIME_PERIODIC :每隔uDelay毫秒周期性地产生事件。
[cpp]
// TestTimer.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <Windows.h>
#include <MMSystem.h>
#pragma comment(lib, "Winmm.lib")
MMRESULT timer_id;
LARGE_INTEGER nFreq;
LARGE_INTEGER nBeginTime;
LARGE_INTEGER nEndTime;
double time;
void WINAPI onTimeFunc(UINT wTimerID, UINT msg,DWORD dwUser,DWORD dwl,DWORD dw2)
{
QueryPerformanceCounter(&nEndTime);
time=(double)(nEndTime.QuadPart-nBeginTime.QuadPart)/(double)nFreq.QuadPart;
printf("%f\n",time);
timeKillEvent(timer_id);
return;
}
int _tmain(int argc, _TCHAR* argv[])
{
QueryPerformanceFrequency(&nFreq);
int n = 0;
QueryPerformanceCounter(&nBeginTime);
timer_id = timeSetEvent(16, 1, (LPTIMECALLBACK)onTimeFunc, DWORD(1), TIME_PERIODIC);
Sleep(1000);
system("Pause");
return 0;
}
[cpp]
[cpp]
通过运行结果可以看到,这个Timer误差在1ms以内,够用了。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
QueryPerformanceCounter实现Windows微秒级延时(转)
Visual C++制作控制系统中微秒级精度定时器
获取系统时间的几种方法,最高精确1ms
QueryPerformanceFrequency() 使用 - 碧海蓝天的日志 - 网易...
使用CPU时间戳进行高精度计时
Windows 各种计时函数总结
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服