Доброго времени суток, встала задача ожидания интервала времени в несколько миллисекунд. Какие устройства компа можно использовать для его отсчета? Пока я вспомнил только про HPEТ, но как его прикрутить не очень разобрался, может есть методы проще? Прерывания использовать нельзя, про int 15h я помню.
А тот PIT судя по-всему не подходит? Интервал должен быть меньшим? Точно... Этот таймер срабатывает через каждые 0.0549 секунд, а мили - порядка 1/1000.
Таймер срабатывает через столько, через сколько его запрограммировать. По дефолту 18 раз в секунду, каждые 0.0549 сек. Это максимально возможный интервал (т.е. самый "медленный"). Можно ускорить в 65535 раз ))
Да, а то я смотрю, что в старом железе вместо HPET'a можно PIT юзать для измерения миллисекундных интервалов. Я с ним не работал, и не догадался сразу о его перепрограммировании... Думал дефолтное значение менять нельзя...
drem1lin Многоуважаемый Pavia где то писал, что out 0x00EB,XX даёт задержку 250 ns (0.25 us = 0.00025 ms). Но я не проверял на сколько это соответствует действительности (на разных конфигурациях).
Не очень понятна фраза, что нельзя использовать прерывания. а) Нельзя вызывать прерывания самостоятельно. б) Нельзя вешать собственные обработчики прерывания. в) Прерывания в системе на момент ожидания запрещены. И сразу поясни, про какие прерывания ты говоришь. Аппаратные, типа IRQ, которые мапятся на софтверные, или именно софтверные прерывания. В общем я знаю про три варианта. 1) использовать счетчик циклов процессора. Лично никогда не использую. 2) Интервальный таймер, с его помощью можно замерить интервалы с точностью до 1/(18.2*256*256), менее 1мкс. Частота счетчика 1.193182МГц. Но для замера больших интервалов требуется довольно сложно объяснимая логика, и/или разрешение IRQ0/INT8 3) Часы реального времени, где тактование счетчика 1024Гц. IRQ8/INT70h. Но как я не бился, получить 1024 прерывания INT70h в секунду не получается. Тебе не обязательно вешать собственный обработчик, можно обойтись и регистрами состояния.
drem1lin, а мультимедийные таймеры не годятся? То есть, функции из mmsystem.dll типа timeGetDevCaps, timeBeginPeriod, SetTimerCallback, timeSetEvent? эти функции специально были разработаны для мультимедийных приложений, работающих с высоким временным разрешением, скажем, порядка требуемых вами миллисекунд.
Отмеривание строго 10 мсек через интервальный таймер вполне легко делается - надо лишь использовать не генерацию меандра (функция 3), а одиночный программный строб (функция 4). В этом режиме после занесения числа таймер однократно отсчитывает до нуля и останавливается, во время счета можно читать состояние. 1. В порту 61h устанавливаем бит 0 в 1 (включаем подачу импульсов на вход таймера) 2. В порт 43h заносим значение 0B8h (10_11_100_0b, 2-й канал, двухбайтовый счет, режим 4, двоичный) 3. В порт 42h заносим младший байт числа (для 10мсек - 9Ch) 4. В порт 42h заносим старшиый байт числа (для 10мсек - 2Eh) 5. В цикле ПО ДВА РАЗА читаем порт 42h (первое чтение - младший, второе - старший байт), до тех пор, пока оба не станут нулевыми. При необходимости можно воспользоваться и промежуточными значениями счета таймера, о неодновременном чтении младший/старший можно не беспокоиться - в таймере стоит 16-разрядная защелка в момент чтения младшего байта, старший байт уже берется не из счетчика, а из защелки.
Кстати, похожий фокус можно провернуть и с прерыванием таймера IRQ0 - заставить таймер выдать однократное прерывание строго через заданный промежуток времени. ТОлько в данном случае надо использовать канал 1 (порт 41h), и управляющее слово будет 78h (01_11_100_0b, 1-й канал, двухбайтовый счет, режим 4, двоичный)
Наврал выше. Не 1-й, 0-й канал для прерывания. Порт 40h и управляющее слово в порт 43h соответственно будет 38h
Странно. Если установлен режим 4 или 0, то счетчик обязан остановиться по достижении нуля и оставаться в нуле до загрузки в счетчик нового значения (отличие режима 0 от режима 4 в выходном сигнале - у режима 4 на выходе после окончания счета возникает один импульс, у режима 0 - уровень держится все время, пока идет счет, но в нашем случае выходной сигнал вобще не важен, поскольку интересует только состояние счетчика). Через пару часов буду дома - проверю.
Есть разные инструкции. В одних он останавливается, в других перескакивает через ноль, и продолжает счет. Так, что пробуй, о результатах доложишь
Изменяй условия выхода, на что-то типа: если прочитанное значение больше ранее прочитанного, или прочитанное значение равно нулю, то выход. На асме что-то типа: @@Loop: .... in al, XXh xchg Ah, Al in al, XXh xchg Ah, Al cmp Ax, Bx mov Ax, Bx jA @@Exit Or Ax, Ax jNZ @@Loop @@Exit: Даже если ты пропустишь переход через НОЛЬ, то у тебя будет 1/18 секунды, что бы это поймать.