我正在使用系统定时器(clock()函数,请参阅time.h)来计算一些串行和USB通信。我需要的只有大约1毫米的准备。我注意到的第一件事是个别时间可以超出(加或减)10毫秒。随着事件的发生,对一些较小的事件进行定时导致时间不准确。总体时间略好一些。在MSDN上有点根后,我偶然发现了Windows多媒体库中的计时器(timeGetTime(),参见MMSystem.h)。在1ms的水平上,这种方法的准确性要好得多。
随后发生了奇怪的事情,经过几天完美无瑕的工作(可爱的日志和有用的时间)之后,所有这些都变成了梨形,因为这个API也开始显示这种奇怪的粒度(而不是一堆小的comms消息需要3ms,2ms,3ms,2ms它出现的时间为0ms,0ms,0ms,0ms,15ms等。重新启动PC恢复了正常的准确度,但是在一些不确定的时间(一小时左右之后),anomoly返回了。
任何人对如何在Windows XP(32位Pro,使用Visual Studio 2008)上获得此级别的计时准确性有任何想法或建议。
我的小课时:
class TMMTimer
{
public:
TMMTimer( unsigned long msec);
TMMTimer();
void Clear() { is_set = false; }
void Set( unsigned long msec=0);
bool Expired();
unsigned long Elapsed();
private:
unsigned long when;
int roll_over;
bool is_set;
};
/** Main constructor.
*/
TMMTimer::TMMTimer()
{
is_set = false;
}
/** Main constructor.
*/
TMMTimer::TMMTimer( unsigned long msec)
{
Set( msec);
}
/** Set the timer.
*
* @note This sets the timer to some point in the future.
* Because the timer can wrap around the function sets a
* rollover flag for this condition which is checked by the
* Expired member function.
*/
void TMMTimer::Set( unsigned long msec /*=0*/)
{
unsigned long now = timeGetTime(); // System millisecond counter.
when = now + msec;
if (when < now)
roll_over = 1;
else
roll_over = 0;
is_set = true;
}
/** Check if timer expired.
*
* @return Returns true if expired, else false.
*
* @note Also returns true if timer was never set. Note that this
* function can handle the situation when the system timer
* rolls over (approx every 47.9 days).
*/
bool TMMTimer::Expired()
{
if (!is_set)
return true;
unsigned long now = timeGetTime(); // System millisecond counter.
if (now > when)
{
if (!roll_over)
{
is_set = false;
return true;
}
}
else
{
if (roll_over)
roll_over = false;
}
return false;
}
/** Returns time elapsed since timer expired.
*
* @return Time in milliseconds, 0 if timer was never set.
*/
unsigned long TMMTimer::Elapsed()
{
if (!is_set)
return 0;
return timeGetTime()-when;
}
答案 0 :(得分:9)
您是否致电timeBeginPeriod(1);
将多媒体分辨率设置为1毫秒?多媒体计时器分辨率是系统全局的,所以如果你没有自己设置,很可能是在其他人调用它之后开始,然后当其他名为timeEndPeriod()
时,分辨率回到系统默认值(通常为10毫秒,如果内存服务)。
其他人建议使用QueryPerformanceCounter()
。这确实具有更高的分辨率,但您仍需要小心。根据所涉及的内核,它可以/将使用x86 RDTSC函数,该函数是指令周期的64位计数器。无论好坏,在时钟频率变化的CPU上(从笔记本电脑开始,但现在几乎无处不在),时钟计数和挂壁时间之间的关系随时钟速度而变化。如果内存服务,如果强制Windows安装时假设有多个物理处理器(而不仅仅是多个内核),那么你将获得一个内核QueryPerformanceCounter()
将读取主板的1.024 MHz时钟。与CPU时钟相比,这降低了分辨率,但至少速度是恒定的(如果你只需要1 ms的分辨率,那么它应该足够了)。
答案 1 :(得分:4)
如果您想在Windows上进行高分辨率计时,则应考虑使用QueryPerformanceFrequency和QueryPerformanceCounter。
这些将提供Windows上最准确的时序,并且随着时间的推移应该更加“稳定”。 QPF为您提供计数/秒,QPC为您提供当前计数。您可以使用它在大多数系统上执行非常高分辨率的计时(ms的分数)。
答案 2 :(得分:1)
查看Win32 API中的高分辨率计时器。
http://msdn.microsoft.com/en-us/library/ms644904(VS.85).aspx
您可以使用它来获得微秒级的分辨率计时器。