Таймер с разрешением 0.8383 микросекунды

Тема в разделе "WASM.ASSEMBLER", создана пользователем mause, 21 фев 2009.

  1. mause

    mause New Member

    Публикаций:
    0
    Регистрация:
    21 фев 2009
    Сообщения:
    9
    Есть модуль
    Код (Text):
    1. unit HTime; {hi-resolution timer}
    2.  
    3. interface
    4.  
    5. procedure InitHTimer;
    6.  
    7. function HTimer:LongInt; {Таймер с разрешением 0.8383 микросекунды}
    8.  
    9. const HTimerRes=0.8383E-6; {Разрешение таймера}
    10.  
    11. implementation
    12.  
    13. procedure InitHTimer; assembler;
    14. asm
    15.   mov   al,$34
    16.   out   $43,al
    17.   xor   ax,ax
    18.   out   $40,al
    19.   out   $40,al
    20. end;
    21.  
    22. function HTimer:Longint; assembler;
    23. asm
    24.   xor   ax,ax
    25.   out   $43,al
    26.   cli
    27.   in    al,$40
    28.   mov   ah,al
    29.   in    al,$40
    30.   xchg  ah,al
    31.   neg   ax
    32.   mov   dx,$40
    33.   mov   es,dx
    34.   mov   dx,[es:$6c]
    35.   sti
    36. end;
    37.  
    38. begin
    39.   InitHTimer;
    40. end.
    Это Паскаль с асемблером, решил это дело переписать не далфи, для WinXP, на что получил сообшение "Privileged instruction" Как заставить работать этот таймер в WinXP, очень нужен.
     
  2. Partner

    Partner Павел

    Публикаций:
    0
    Регистрация:
    28 фев 2008
    Сообщения:
    917
    Адрес:
    Los Angeles
    mause
    В user mode нельзя обращаться к портам. Нужен драйвер.
     
  3. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Partner
    Ошибаетесь, пути два - IOPL(EFlags.IOPL) и IOPM, первый способ доступен из юзермода посредством сервиса NtSetInformationProcess(ProcessUserModeIOPL).
    Кстати по коду замечание - это не выполнить из юзермода, период таймера меньше чем квант потока.
     
  4. Partner

    Partner Павел

    Публикаций:
    0
    Регистрация:
    28 фев 2008
    Сообщения:
    917
    Адрес:
    Los Angeles
    Clerk
    Слышал, что NtSetInformationProcess(ProcessUserModeIOPL) не работает на AMD. Не знаю правда ли.
     
  5. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    А в чем смысл использовать такой таймер?
     
  6. Partner

    Partner Павел

    Публикаций:
    0
    Регистрация:
    28 фев 2008
    Сообщения:
    917
    Адрес:
    Los Angeles
    Pavia
    Повторное использование кода :)
     
  7. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Я реализовал подобное, но исполь PIT, по крайней мере есть свободный канал и быстрее чем мультимедиа-таймеры и пр. механизмы предоставляемые юзермодному коду.
     
  8. mause

    mause New Member

    Публикаций:
    0
    Регистрация:
    21 фев 2009
    Сообщения:
    9
    Pavia
    Смысл скрыт глубоко в проблеме, сейчас опишу, есть АЦП(аналогово-цифровой преобразователь) к нему подключены фотодатчики которые измеряют скорость врашения, но фотодатчики то не простые, а сложные, и поэтому выдают на ацп не саму частоту врашени, а просто сигнал, если быть точным то прерывание, зная что один оборот мы имеем 2500 сигналов(характеристика датчика) то мы можем вычислить частоту врашения, но тогда возникат проблема получения частоты врашения в реальном времени( мы не можем ждать пока датчик обернется 2500 раз и замерить это время стандартным таймером, т.к это может быть как очень долго так и очень быстро, диапазон частот врашения от 50 до 1000 об/мин, поэтому был найден вот этот замечательный для нас модуль, и мы измеряли время между сигналами и вычисляли так скорость врашения. Все было хорошо пока не возникла необходимость перейти на WinXP. Вот и вся проблема. Если подскажете как можно реализовать таймер с примерно таким разрешением то буду очень благодарен!
     
  9. Partner

    Partner Павел

    Публикаций:
    0
    Регистрация:
    28 фев 2008
    Сообщения:
    917
    Адрес:
    Los Angeles
    0.8383 микросекунды или миллисекунды ?
     
  10. Exp10der

    Exp10der Мастер дзена

    Публикаций:
    0
    Регистрация:
    27 авг 2007
    Сообщения:
    337
    Адрес:
    Красноярск
    юзай внешний контроллер
     
  11. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    А если сделать так (но придется установить потоку одно ядро, если их несколько и приоритет реального времени для большей точности)
    определяем частоту процессора в тактах через rdtsc, во время последнего схваченного прерывания от устройства сохраняем значение счетчика тактов отнимаем от предыдущего значения и делим на частоту. получаем время довольно точно. я так делая и на IC2Q работает превосходно.
     
  12. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    max7C4
    Именно так и должно быть, обработка данных начнётся по приходу прерывания.
    Приоритет мало что изменит, изначально не верный подход. В отличие от доса мультизадачная ось не должна таким образом обслуживать устройства, ибо всё повиснет. Как правильно заметил Exp10der используй внешний контроллер, который исполнит подсчёт и предварительную обработку данных. Возьми к примеру мышку - непосредственно с датчиков поток данных не поступает на порт, он проходит обработку внутренним контроллером и отсылаются только изменения состояния датчиков уже пересчитанные по прерыванию.
     
  13. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    Clerk
    Зачем микро контроллер ему время между прерываниями замерить надо.

    Код (Text):
    1. uses mmsystem;
    2. // Частота соизмерима с частотой процессора.
    3. function RDTSC: Int64; register;
    4. asm
    5. RDTSC
    6. end;
    7.  
    8.  
    9. function GetRDTSCSpeed:Int64;  // Функция возращает скорость RDTSC в тактах
    10. var t1,t2,tt1,tt2:Int64;
    11.     r:Real;
    12.     i,j:Integer;
    13. begin
    14. SetThreadAffinityMask(GetCurrentThread, 1);  // Привязываем выполнение к первому ядру
    15. Sleep(0); // Нужно для избежания ошибок RDTSC
    16.  
    17. timeBeginPeriod(1); // Устанавливаем время сробатывания мультимидийного таймера в 1мкс
    18. t1:=timeGetTime();
    19. repeat
    20. t2:=timeGetTime();
    21. tt1:=RDTSC;
    22. until t2-t1>60;
    23. t1:=t2;
    24. repeat
    25. tt2:=RDTSC;
    26. t2:=timeGetTime();
    27. until t2-t1>1000;
    28.  
    29. r:=round((tt2-tt1)/(t2-t1));
    30.  
    31. // Корректируем результаты измерения.
    32. j:=0;
    33. for i:=1 to 4000 do
    34.  if abs(r-i*14318.180/3)<abs(r-j*14318.180/3) then
    35.    j:=i;
    36. result:=Round(j*14318180.0/3);
    37. end;
    38.  
    39. procedure TForm1.Button1Click(Sender: TObject);
    40. var C,RDTSCSpeed,tttt1,tttt2:Int64;
    41. i:Integer;
    42. begin
    43. // Пример измерения
    44. RDTSCSpeed:=GetRDTSCSpeed;
    45. tttt1:=RDTSC;
    46. tttt2:=RDTSC;
    47. c:=tttt2-tttt1;
    48. tttt1:=RDTSC;
    49. sleep(0);  // То что мерим
    50.  
    51. tttt2:=RDTSC;
    52. caption:=format('RDTSCSpeed=%.9f МГц; Результат= %.9f c ; %.9f такты',[RDTSCSpeed/ 1000000,(tttt2-tttt1-c)/RDTSCSpeed,(tttt2-tttt1-c)/1]);
    53. end;
     
  14. Exp10der

    Exp10der Мастер дзена

    Публикаций:
    0
    Регистрация:
    27 авг 2007
    Сообщения:
    337
    Адрес:
    Красноярск
    Pavia timeBeginPeriod(1); время в миллисекундах
     
  15. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Pavia
    Ну попробуй обработай в юзермоде прерывание..
    Кстати а почемуб на ИС не сделоть. У меня когдато такая идея была. Решил частоту мерить цифрового сигнала, высокую, десятки/сотни MHz. Реализация на бумаге была проста. Тактовый кварцованный генератор вырабатывал импульс фиксированной длительности со счётчика(исходная частота делилась). За время этого импульса другим счётчиком подсчитывалось число импульсов исходного сигнала. Там весьма простая логика была, несколько счётчиков и лог. микросхем. На выходе параллельным кодом выдавалось число импульсов за фиксированный интервал времени. Почемуб и тут так не сделоть(если с контроллером не подходит).
     
  16. mause

    mause New Member

    Публикаций:
    0
    Регистрация:
    21 фев 2009
    Сообщения:
    9
    Partner микро, в то и проблема, за милиросекунду несколько прерываний пройти успеть может.
    Спасибо за советы, внешний контролер слишком муторно будет,хотя и очень перспективно с точки зрения дальшейней модернизации. А вот идея Clerk мне очень понравилась, попробую так сделать.
    Я тут вот что подумал, в DOS у меня не было возможности сделать многопоточное приложение, теперь эта возможность есть, поэтому попробуем считать частоту вращения в другом потоке. Там же будем считать и координаты... датчика то 3, я забыл сказать.
    Огросное спасибо за советы, как сделаю отпишусь что получилось и как делал.
     
  17. Partner

    Partner Павел

    Публикаций:
    0
    Регистрация:
    28 фев 2008
    Сообщения:
    917
    Адрес:
    Los Angeles
    mause
    Микро - не взлетит. Нужно апаратное решение.

    1000 об/мин - это один оборот за 60 миллисекунд. Откуда микросекунды?
     
  18. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    Partner
    #8 - 2500 срабатываний датчика на оборот
    mause
    Если на асме кодишь, то Атмел освоишь легко :) это удобнее и универсальнее отдельных микросхем.
     
  19. mause

    mause New Member

    Публикаций:
    0
    Регистрация:
    21 фев 2009
    Сообщения:
    9
    Y_Mur
    проблема в том что асм я почти не знаю, все на что меня хватило это вон тот модуль в первом сообщении.
    Исходя из вышеперечисленого, я подумал, что реализовать подобный таймер на WinXP довольно проблематично, и лучше искать обходные пути....
     
  20. ConstZ

    ConstZ New Member

    Публикаций:
    0
    Регистрация:
    18 фев 2008
    Сообщения:
    42
    1. Не совсем понятно, зачем там нужен АЦП? Сигнал от датчика можно просто подать на формирователь импульса (компаратор). Если же АЦП действительно в наличии, то достаточно между выходом датчика и аналоговым входом АЦП поставить RC цепочку и получать непосредственно числовые данные, пропорциональные частоте вращения.

    2. Мне кажется, не имеет практического смысла считать интервалы времени между каждым входным импульсом: лучше считать сами импульсы за определённый промежуток времени. Например, если данные о частоте вращения требуется знать, скажем один раз в секунду, то можно запрограммировать простенький обработчик прерываний - счётчик, значения которого анализируются один раз в секунду. Если и в этом случае Ваш компьютер "захлебнётся" прерываниями, - поделить сигнал от АЦП простейшим аппаратным счётчиком на одной микросхеме.