Я использовал системный таймер (функция clock (), см. Time.h) для определения времени некоторых последовательных и USB-коммуникаций. Все, что мне было нужно, это точность около 1 мс. Первое, что я заметил, это то, что отдельные времена могут быть (плюс или минус) 10 мс. Сроки ряда меньших событий привели к менее точным срокам по мере прохождения событий. Совокупные сроки были немного лучше. После небольшого рута в MSDN и т. Д. Я наткнулся на таймер в мультимедийной библиотеке Windows (timeGetTime (), см. MMSystem.h). Это было намного лучше с приличной точностью до уровня 1 мс.
Затем возникла странность, после первоначальной безупречной работы в течение нескольких дней (прекрасные журналы с полезными таймингами) все стало грушевидным, так как этот API также начал показывать эту странную гранулярность (вместо набора небольших сообщений от 3 до 2 мс, 3 мс, 2 мс , 3 мс и т. Д. Получилось как 0 мс, 0 мс, 0 мс, 0 мс, 15 мс и т. Д. Перезагрузка ПК восстановила неточность, но через некоторое неопределенное время (примерно через час) аномалия вернулась.
Кто-нибудь получил какие-либо идеи или предложения о том, как получить такой уровень точности синхронизации в 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;
}