Трубется сделать задержку в 5-10 мкс. Нашёл такую конструкцию: int tkt; double PCFreq = 0.0; __int64 CounterStart = 0; void StartCounter() { LARGE_INTEGER li; QueryPerformanceFrequency(&li); PCFreq = double(li.QuadPart)/1000000.0; QueryPerformanceCounter(&li); CounterStart = li.QuadPart; } double GetCounter() { LARGE_INTEGER li; QueryPerformanceCounter(&li); return double(li.QuadPart-CounterStart)/PCFreq; } int zaderzhka() //функция организующая задержку { StartCounter(); do { tkt = GetCounter(); } while(tkt <= /" здесь выставляю задержку "/ ); return 0; } Всё работает, но задержка не стабильная, прыгает (+-5 мкс) . Есть ли ещё какой-нибуль способ организовать задержку в микросекундах? Вычитал что можно вставку asm сделать, но я это не в состоянии сделать. (программирую полторы недели, работа требует) Есть какие-нибудь предложения? Пишу в C++ Buider 6
finger Данная задача не реализуется на ПК, в виду наличия вытесняющей многозадачности и неизвестных параметров системы. Для этого нужен микроконтроллер с достаточно известными параметрами. А зачем вам задержка 5 мкс?
KeDelayExecutionThread, но это исключительно в ядре, и соответственно в драйвере который должен работать с неким устройством. а вообще есть некое извращение с помощью select из винсока http://stackoverflow.com/questions/85122/sleep-less-than-one-millisecond касаемо асма только это пришло в голову. задержка на приблизительное число тактов проца. чтобы это дело перевести в мкс полагаю следует рассчитать время одного такта Код (Text): // писал на визуал студии, хз как там билдер ключевые слова понимает #include "stdafx.h" __declspec(naked) __forceinline void __fastcall DelayExecutionTicks(unsigned int TickCount) { __asm { rdtsc mov esi, eax _loop: rdtsc sub eax, esi cmp eax, ecx jbe _loop ret } } int _tmain(int argc, _TCHAR* argv[]) { int i_thpriority; i_thpriority = GetThreadPriority(GetCurrentThread()); SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); DelayExecutionTicks(0x300); SetThreadPriority(GetCurrentThread(), i_thpriority); return 0; }
Лет 5-7 назад здесь, на Васме, приводил пример, как можно делать точные маленькие задержки на циклах. Идея такая. 1. Задержки выполняются в потоках с приоритетом TimeCritical циклами типа: for (i=0;i<N;i++) { _asm { sub eax, eax cpuid } } 2. Тут надо знать точное значение N. Если просто измерить цикл для какого-нибудь N0, а потом увеличить или уменьшить N в нужное количество раз, то задержки получатся завышенными на несколько мкс. Дело в том, что задержка в цикле состоит из 2 частей, где одна часть С - собственно цикл, а другая D - накладные расходы. Поэтому предварительно делаем 2 цикла с разными N (например, N1=10000000 и N2=25000000) и измеряем их времена T1 и T2 при помощи RDTSC. Получаем систему двух уравнений: T1 = C*N1 + D T2 = C*N2 + D, из которой находим C=(T2-T1)/(N2-N1) и D=(T1*N2-T2*N1)/(N2-N1) - это константы для данного процессора с данной частотой. Я все это делал на этапе инициализации 1 раз. 3. Пусть теперь нужно получить задержку T, имеем уравнение T = D + C*n, из которого находим точное значение n=(T-D)/C, и уже с этим количеством делаем цикл. Он будет продолжительностью T, и погрешности на практике очень хорошие: плюс минус 1 мкс. 4. Но! Винда - не ось реального времени. Даже если выставить у потока приоритет Time Critcal, раз в 4-5 секунд этот поток все равно будет прерван, причем надолго. То есть, это означает, что такие маленькие точные задержки можно делать не непрерывно, а изредка, и почаще отдыхать - возвращая NormalPriority и делая Sleep(0). Если такой режим работы по условиям задачи не подходит - сорри, ищите другую ось. 5. На многоядерных не пробовал, т.к. не было необходимости.
Не проще ли воспользоваться мультимедийными таймерами с колбэком или ивентом? timeSetEvent, разрешение/точность задается timeBeginPeriod.
Dmitry_Milk Длительность кванта больше чем необходимая задержка. Посему планирование не избежно придётся вырубить. Но так как между квантами есчо и прерывания робят, а они не прекращаются принудительно, то и их выключить придётся. Тоесть либо диспатч из ISR, либо лок камня в цикле.