Форум: "WinAPI";
Текущий архив: 2005.08.28;
Скачать: [xml.tar.bz2];
Внизвозвращаясь к задержкам ... Найти похожие ветки
← →
Vallos (2005-07-05 16:08) [0]Возникла необходимость устанавливать задержку выполнения программы (и менее 1 мс). Вроде бы и хорошая реализация:
procedure Delay_(ms: double);
var
x1, x2, freq: Int64;
begin
QueryPerformanceFrequency(freq);
QueryPerformanceCounter(x1);
repeat
QueryPerformanceCounter(x2)
until (x2-x1 >= 0.001*ms*freq);
end;
Все четко и красиво работает (от мкс до с), единственное - когда все процессы на машине заморожены: стоит повести мышкой - четкость и красота пропадает ... RDTSC работает аналогичным образом ...
Вопрос в следующем: есть ли другие реализации без привязки к частоте процика (частота которого плавает и в "спящем режиме") или чегото ещё...
← →
alpet © (2005-07-05 16:24) [1]Тебе вероятно нужно изучить мультимедийные таймеры - они позволяют оперировать такими задержками.
functions:
timeBeginPeriod
timeEndPeriod
timeGetDevCaps
timeGetSystemTime
timeGetTime
timeKillEvent
TimeProc
timeSetEvent
← →
Digitman © (2005-07-05 16:30) [2]
> Vallos
> менее 1 мс
а можно полюбопытствовать, за каким лядом такая дискретность понадобилась в мультизадачной (а не риэл-тайм) среде ?
← →
Ботвин Дмитрий (2005-07-05 16:44) [3]А-га, и причём в среде с вытесняющей многозадачностью, где
каждому потоку тока по 20мс, примерно, отводится процессорного
времени :-)))
← →
Ботвин Дмитрий (2005-07-05 16:48) [4]Кстати, такие задержки с помощью QueryPerformanceFrequency
и QueryPerformanceCounter не реализовать. Они принимают допущения, что твой поток не вытесняется более приоритетными, а
работает не прерывно. Поэтому движения мышкой и нарушают всю красоту, как ты говоришь. Этот поток и куча других, более приоритетных, будут вносить погрешности...
← →
Vallos (2005-07-05 17:00) [5]... согласен, что QueryPerformanceCounter не катит, а что катит?
> 2 Digitman: для работы с внешними устройствами...
2All: кстати, sleep(x) вполне корректно спавляется с поставленной задачей, правда только от 1 мс, с дискретностью 1 ...
← →
Digitman © (2005-07-05 17:03) [6]
> Vallos (05.07.05 17:00) [5]
> для работы с внешними устройствами
для работы с периферией, требующей такую временную дискретность и прецизионность Win32 никаким боком не подходит - нужна риэл-тайм опер.система, хоть тот же ДОС
← →
Ботвин Дмитрий (2005-07-05 17:05) [7]А ты что замерял чем-то этот интервал? С чего ты взял, что
Sleep обеспечивает задержку в 1мс? Если передал ей такой параметр, это не значит, что твой поток замер ровно на 1мс. Если в этот момент времени появился в списке планируемых потоков поток
с более высоким приоритетом, то планировщик потоков именно ему
выделит квант процессорного времени, а твой продолжит работать тока после него и реальная задержка может оказаться гараздо больше чем 1мс....
← →
alpet © (2005-07-05 17:43) [8]Если важна точность - придется перебираться на другую ось, например Qnx или Dos. Под Windows нет возможности работать с оборудованием в режиме реального времени.
← →
Игорь Шевченко © (2005-07-05 18:05) [9]
> Если важна точность
Ее надо реализовать аппаратно.
← →
Vallos (2005-07-05 18:09) [10]> 2Ботвин Дмитрий: я не утверждаю, что там 1.000 мс, просто стабильно держит (смотрем спецпримочками своей реализации на осциллографе, если это интересно)...
Перебраться на другую ось проблематично, желательни иметь привязку к "народной" ...
А слип в делфях реализуется как
{$IFDEF MSWINDOWS}
procedure Sleep; external kernel32 name "Sleep"; stdcall;
{$ENDIF}
{$IFDEF LINUX}
procedure Sleep(milliseconds: Cardinal);
begin
usleep(milliseconds * 1000); // usleep is in microseconds
end;
{$ENDIF}
как видно, альтернатива usleep - kernel32...
← →
alpet © (2005-07-05 18:19) [11]Vallos (05.07.05 18:09) [10]
В этом случае гарантий точности никаких, но вместе с тем высокоприоритетный поток имеет большие шансы на отработку с данным интервалом (1мс), хотя раз уж работа идет с железом - синхронизировать лучше с железом. Опять же - изучайте мультимедийные таймеры высокого разрешения - это одина из немногих возможностей задавать такую небольшую задержку. Про sleep лучше вообще забыть, эта функция не дает требуемой точности.
← →
Vallos (2005-07-05 18:24) [12]Испробую завтра timeGetTime и иже с ними, результат сообщу...
Железная реализация хороша, но требует дополнительные узлы, которые можно было бы реализовать программно ...
← →
Vallos (2005-07-06 11:37) [13]... не пробовал ... Потому что все равно больше 1 мс с дискретностью 1 мс ...
Испробовал вот что:
procedure
var
t1, t2: TDateTime;
begin
t1:= Now;
repeat
// простое действие;
t2:= Now-t1;
until t2 >= 0.000001157407407; // 0.1 с
Label1.Caption:= FloatToStr(t2/0.0000115740740740740741)
- результат в Label1 был от 0,1089997 до 0,1100006...
"простое действие" можно исключить, результат тотже. Можно ли как-то процес ускорить (делать не через Now).
Интересная деталь: код
t1:= Now;
for i:= 1 to 50000 do t2:= Now-t1;
Label2.Caption:= FloatToStr(t2/0.000011574074074074074074074)
дает результаты от 0,01500004 до 0,01600021.
Минимальное значение i, при котором еще не 0 - 32000, но и значения такие же, как и при 60000, при 65000 и выше знечение увеличивается в 2 раза ...
А как использовать таймер 8253 (или какой там стоит)?
← →
Ботвин Дмитрий (2005-07-06 12:05) [14]У тебя комп тока как контроллер внешнего устройства работает или
ещё в интерактивном режиме? От этого много зависит...
← →
Vallos (2005-07-06 12:45) [15]В том то и дело, что в интерактивном (если я правильно понимаю): контроллер запустился себе и трудится, а тем временем можно и пасьянс разложить (doom побегать), в Word-е покопаться и тп.
← →
alpet © (2005-07-06 12:56) [16]Не по API это все. Программы прикладного режима и думать не должны от прямой работе с таймером. Если ваш CPU поддерживает инструкцию rdtsc - можно и ей воспользоватся для отмеряния промежутков времени, но при этом процесс должен будет работать практически монопольно - с максимальным приоритетом - мышь вообще лучше отключить во время эксплуатации.
← →
Ботвин Дмитрий (2005-07-06 13:00) [17]Тогда это нереально в принципе. Можно помесетить код, выполняющий задержку на 1мс и менее в поток и присвоить ему
высокий приоритет. Или ещё лучше поместить его в критическую
секцию и пока он не выйдет из неё никто его не вытеснет. Но тогда процесс Expolorer, который и отвечает за отклик на действия юзера, просто не сможет запустить свои потоки и юзер
через некоторое время подумает, что его комп завис и нажмет
резет. Отсюда 2 варианта:
1. Сделать комп контроллером и не сажать за него юзера. Тогда
можно и с потоками поэксперементировать.
2. Перейти на реал-тайм ОС(например дос), а вместо D6 -
TurboPascasl, а ещё лучше С++.
По-другому я думаю не получится - виндус не работает в режиме
реального времени с оборудованием, да ещё когда там юзер по-пустякам процессор отвлекает :-)))
← →
Vallos (2005-07-06 14:45) [18]А если вернуться к "независимому" системному таймеру 8253 (х)...
У него частота тактов 1193180 Гц (Джорджейн, Справочник программста ПК типа РС, ХТ и АТ), и каким-то макаром (не понял как) "задвижками" можно изменять интервал таймера (%?), но при этом нужно восстанавливать оригинальное значение задвижки после отработки задачи (приоритет задачи получается архивысокий) ... (муть)
← →
Digitman © (2005-07-06 14:55) [19]
> приоритет задачи получается архивысокий
какое отношение приоритет (процесса, трэда) имеет к программированию и возможностям 8253 ?
← →
Vallos (2005-07-06 15:03) [20]... не знаю ...
Так можно ли реализовать определение текущего времени не через TDateTime, а (допустим) возможностями 8253?
← →
Digitman © (2005-07-06 15:12) [21]определись сначала, что для тебя есть "текущее время" ..
← →
Vallos (2005-07-06 15:45) [22]
procedure
var
t1, t2: TFTime;
begin
t1:= GetTimeNew; // функция определения "текущего времени"
// выполняемое действие;
repeat
t2:= GetTimeNow-t1;
// можно всунуть Application.ProcessMessages для больших периодов
until t2 >= mks;
end;
Вот что мне хотелось бы получить на выходе, чтобы обеспечивать задержку от 0.1 мкс
← →
Digitman © (2005-07-06 15:58) [23]
> функция определения "текущего времени"
нет, а 8253-то к этому какое отношение имеет ?
8253 не занимается ни подсчетом, ни контролем, ни хранением "текущего времени", этоже не часы, это - таймер !
> можно всунуть Application.ProcessMessages для больших периодов
это еще зачем ?
ты аппаратурой собрался управлять в тек.трэде или свистки/звонки/картинки показывать капризному юзеру, чтобы не заснул, да за мышкой/клавой следить ?
← →
Kerk © (2005-07-06 16:06) [24]Вот прохожу мимо ветки регулярно.. и постоянно сабж не в том смысле понимаю.. блин..
← →
Vallos (2005-07-06 16:10) [25]... я наверное начинаю надоедать (, а модератор перенесет эту ветку в ПОТРЕПАТЬСЯ)...
Из нереального:
- в начальный момент записать в таймер задержку, обнулить, запустить;
- отработать свое действие (таймер считает);
- ожидать отработки счета таймера, при окончании запустить поновому, и так далее ...
Т.е. отработать действие не по окончании счета таймера, а во время счета ... // это по поводу 8253 ...
← →
Digitman © (2005-07-06 16:18) [26]
> я наверное начинаю надоедать
эт точно)
тебе же сказали - среда у тебя МУЛЬТИЗАДАЧНАЯ !
а ты все про свой 8253 гнешь)
← →
Digitman © (2005-07-06 16:20) [27]
> ожидать отработки счета таймера
что ты, спрашивается, будешь "ожидать", если таймер "тикнет" раньше, чем ты "отработаешь свое действие" ?
ты же НЕ МОЖЕШЬ знать, сколько времени будет исполняться "твое действие" !
← →
Vallos (2005-07-06 16:34) [28]... я предупреждал - Из нереального ...
... само-собой, что продолжительность действия должно быть меньше времени счета таймера ...
Не будем нагнетать обстановку, будем потихоньку расходиться (буду просмотривать эту ветку, может что еще подскажите) ...
Благодарю всех за участие ...
← →
alpet © (2005-07-06 16:35) [29]Как это можно сделать для WINDOWS (источник сигналов):
1. Потребуется звуковая карта.
2. Устанавливаем к примеру следующие параметры воспоизведения (можно через DirectSound):
"дискретизация: 22050гц, разрядность 8 бит, моно".
Это означает что выборка DAC звуковой карты будет осуществляться 22050 раз в секунду, а нам надо чтобы импульсы шли через 1 мс (иными словам 1000 гц писк). Из этого следует, что в буфере воспроизведения максимальные значения амплитуды с минимальным (255 и 0) чередовались через 11,25 выборок или такое же количество байт. Этот звук можно впринципе легко сгенерировать програмно, и после этого зациклить буфер на воспроизведение. Сигнал можно будет снимать через триггер с звукового выхода.
Для большей точности сооветственно выбирается большая частота дискретизации.
Если нужно принимать сигналы - соотвественно используется запись с линейного входа.
← →
Digitman © (2005-07-06 16:44) [30]
> Vallos (06.07.05 16:34) [28]
в пнринципе, если таки хочется поизвращаться, можно на короткие промежутки времени получить возможность поработать в риэл-тайм
пишешь драйвер режима ядра, в нем ты запрещаешь все прерывания (в т.ч. - немаскируемые) и, пока ты их вновь не разрешишь, ни один процесс и ни один трэд процесса не получит управления, пока ты вдоволь не натешишься "таймерами")
← →
Германн © (2005-07-07 01:31) [31]2 alpet © (06.07.05 16:35) [29]
Ну честно сказать - очередное "извращение". Попытка "применить неприменимое"!
Можно написать некий драйвер для звуковой карты. Но не лучше ли создать "внешнее устройство с АЦП и ЦАП" контроллируемое микропроцессором, а многие из них имеют встроенные АЦП и ЦАП!?
← →
alpet © (2005-07-07 08:21) [32]Германн © (07.07.05 01:31) [31]
Собственно автору и нужны "извращения" :) Хотя бы потому что в MustDie, да еще и в user-mode. Что касается драйвера - не понял, для чего? Звук частотой 1000 Гц можно сгенерировать и в SoundForge .
← →
begin...end © (2005-07-07 08:32) [33]> Kerk © (06.07.05 16:06) [24]
"Жениться тебе надо, барин" (с)
:-)
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2005.08.28;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.036 c