Как сделать таймер в паскале

Добавил пользователь Алексей Ф.
Обновлено: 10.09.2024

Большинство программ, которые вы пишете, нуждаются в реализации некоторой формы функций даты, возвращающих текущую дату и время. Свидания настолько важны в повседневной жизни, что с ними легко работать, не задумываясь. Паскаль также предоставляет мощные инструменты для арифметики дат, которые упрощают манипулирование датами. Однако фактическое имя и работа этих функций различны для разных компиляторов.

Получение текущей даты и времени

Функция Pascal TimeToString дает вам текущее время в форме с разделителями (:). В следующем примере показано, как получить текущее время —

Когда приведенный выше код был скомпилирован и выполнен, он дает следующий результат —

Функция Date возвращает текущую дату в формате TDateTime . TDateTime — это двойное значение, которое требует некоторого декодирования и форматирования. Следующая программа демонстрирует, как использовать ее в вашей программе для отображения текущей даты:

Когда приведенный выше код был скомпилирован и выполнен, он дает следующий результат —

Функция Now возвращает текущую дату и время —

Когда приведенный выше код был скомпилирован и выполнен, он дает следующий результат —

Free Pascal предоставляет простую структуру меток времени с именем TTimeStamp , которая имеет следующий формат:

Различные функции даты и времени

Free Pascal предоставляет следующие функции даты и времени —

function DateTimeToFileDate (DateTime: TDateTime): LongInt;

Преобразует тип DateTime в дату файла.

Функция DateTimeToStr (DateTime: TDateTime) :;

Создает строковое представление DateTime

function DateTimeToStr (DateTime: TDateTime; const FormatSettings: TFormatSettings) :;

Создает строковое представление DateTime

процедура DateTimeToString (out Результат:; const FormatStr:; const DateTime: TDateTime);

Создает строковое представление DateTime

процедура DateTimeToString (out Результат:; const FormatStr:; const DateTime: TDateTime; const FormatSettings: TFormatSettings);

Создает строковое представление DateTime

процедура DateTimeToSystemTime (DateTime: TDateTime; выход SystemTime: TSystemTime);

Преобразует DateTime в системное время

function DateTimeToTimeStamp (DateTime: TDateTime): TTimeStamp; Преобразует DateTime в метку времени

Функция DateToStr (Date: TDateTime) :;

Создает строковое представление даты

function DateToStr (Date: TDateTime; const FormatSettings: TFormatSettings) :;

Создает строковое представление даты

Функция Date: TDateTime;

Получает текущую дату

function DayOfWeek (DateTime: TDateTime): Integer;

Получает день недели

процедура DecodeDate (Дата: TDateTime; год выхода: слово; месяц выхода: слово; день выхода: слово);

Декодирует DateTime в год, месяц и день

процедура DecodeTime (время: TDateTime; вне часа: слово; вне минуты: слово; вне секунды: слово; вне миллисекунды: слово);

Декодирует DateTime в часы, минуты и секунды

функция EncodeDate (год: слово; месяц: слово; день: слово): TDateTime;

Кодирует год, день и месяц в DateTime

функция EncodeTime (час: слово; минута: слово; секунда: слово; миллисекунда: слово): TDateTime;

Кодирует часы, минуты и секунды в DateTime

Функция FormatDateTime (const FormatStr:; DateTime: TDateTime) :;

Возвращает строковое представление DateTime

функция FormatDateTime (const FormatStr:; DateTime: TDateTime; const FormatSettings: TFormatSettings) :;

Возвращает строковое представление DateTime

функция IncMonth (const DateTime: TDateTime; NumberOfMonths: Integer = 1): TDateTime;

Добавляет 1 к месяцу

function IsLeapYear (Год: Слово): Boolean;

Определяет, является ли год високосным

function MSecsToTimeStamp (MSecs: Comp): TTimeStamp;

Преобразует количество миллисекунд в метку времени

функция сейчас: TDateTime;

Получает текущую дату и время

function StrToDateTime (const S :): TDateTime;

Преобразует строку в DateTime

function StrToDateTime (const s: ShortString; const FormatSettings: TFormatSettings): TDateTime;

Преобразует строку в DateTime

function StrToDateTime (const s: AnsiString; const FormatSettings: TFormatSettings): TDateTime;

Преобразует строку в DateTime

function StrToDate (const S: ShortString): TDateTime;

Преобразует строку в дату

function StrToDate (const S: Ansistring): TDateTime;

Преобразует строку в дату

function StrToDate (const S: ShortString; разделитель: Char): TDateTime;

Преобразует строку в дату

function StrToDate (const S: AnsiString; разделитель: Char): TDateTime;

Преобразует строку в дату

function StrToDate (const S: ShortString; const useformat:; разделитель: Char): TDateTime;

Преобразует строку в дату

function StrToDate (const S: AnsiString; const useformat:; separator: Char): TDateTime;

Преобразует строку в дату

Важные выдержки оттуда:

Кроме часов реального времени, любой компьютер (даже простейший IBM PC) содержит устройство, называемое системным таймером. Это устройство подключено к линии запроса на прерывание IRQ0 и вырабатывает прерывание INT 8h приблизительно 18,2 раза в секунду (точное значение - 1193180/65536 раз в секунду).

При инициализации BIOS устанавливает свой обработчик для прерывания таймера. Этот обработчик каждый раз увеличивает на 1 текущее значение четырехбайтовой переменной, располагающейся в области данных BIOS по адресу 0000:046Ch - счетчик тиков таймера. Если этот счетчик переполняется (прошло более 24 часов с момента запуска таймера), в ячейку 0000:0470h заносится 1.

Другое действие, выполняемое стандартным обработчиком прерывания таймера - контроль за работой двигателей НГМД. Если после последнего обращения к НГМД прошло более 2 секунд, обработчик прерывания выключает двигатель. Ячейка с адресом 0000:0440h содержит время, оставшееся до выключения двигателя. Это время постоянно уменьшается обработчиком прерывания таймера. Когда оно становится равно 0, обработчик выключает двигатель НГМД.

Таймеру соответствуют четыре порта ввода/вывода со следующими адресами:

40h - канал 0;
41h - канал 1;
42h - канал 2;
43h - управляющий регистр.
Приведем формат управляющего регистра:

7 6 5 4 3 2 1 0
T-T-T-T-T-T-T-¬
¦ ¦ ¦ ¦ ¦
LT+T+T+T+T+-+T+T-
LT- LT- L=T=- L= BCD: 0 - двоичный счет;
¦ ¦ ¦ 1 - двоично-десятичный счет.
¦ ¦ ¦
¦ ¦ L===== M: 000 - режим 0;
¦ ¦ 001 - режим 1;
¦ ¦ X10 - режим 2;
¦ ¦ X11 - режим 3;
¦ ¦ 100 - режим 4;
¦ ¦ 101 - режим 5.
¦ ¦
¦ L========== RW: 00 - код команды CLC (запомнить CE);
¦ 01 - чтение/запись старшего байта;
¦ 10 - чтение/запись младшего байта;
¦ 11 - чтение/запись младшего, затем
¦ старшего байта.
¦
L============== SC: 00 - канал 0;
01 - канал 1;
10 - канал 2;
11 - код команды RBC (чтение состояния канала).

Поле BCD определяет формат константы, использующейся для счета - двоичный или двоично-десятичный. В двоично-десятичном режиме константа задается в диапазоне 1-9999.

Поле M определяет режимы работы микросхемы 8254:

0 - прерывание от таймера;
1 - программируемый ждущий мультивибратор;
2 - программируемый генератор импульсов;
3 - генератор меандра;
4 - программно-запускаемый одновибратор;
5 - аппаратно-запускаемый одновибратор.
Мы будем рассматривать только режим 3, так как именно он используется в каналах 0 и 2.

Поле RW определяет способ загрузки констант через однобайтовый порт. Если в этом поле задано значение 00, это управляющее слово будет использоваться для фиксации текущего содержимого регистров счетчика CE в буферном регистре OL с целью чтения программой. Это код команды CLC - фиксация регистров. Код канала, для которого будет выполняться фиксация, должен быть указан в поле SC. Поля M и BCD при этом не используются.

Поле SC определяет номер канала, для которого предназначено управляющее слово. Если в этом поле задано значение 11, будет выполняться чтение состояния канала.

Приведем формат команды RBC чтения слова состояния канала:

7 6 5 4 3 2 1 0
T-T-T-T-T-T-T-¬
¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦
LT+T+T+T+T+T+T+T-
LT- ¦ ¦ ¦ ¦ ¦ L= равно 0.
¦ ¦ ¦ ¦ ¦ ¦
¦ ¦ ¦ ¦ ¦ L=== 1 - выбор канала 0.
¦ ¦ ¦ ¦ L===== 1 - выбор канала 1.
¦ ¦ ¦ L======= 1 - выбор канала 2.
¦ ¦ ¦
¦ ¦ L========= STAT: 0 - читать состояние каналов;
¦ ¦ 1 - не читать состояние каналов.
¦ ¦
¦ L=========== CNT: 0 - запомнить текущее содержимое CE;
¦ 1 - не запоминать содержимое CE.
¦
L============== код команды RBC - 11.

С помощью этой команды вы можете выполнять операции чтения состояния каналов либо запоминание регистра счетчика CE каналов. Можно выполнять эти операции как для отдельных каналов, так и для всех каналов одновременно, если установить соответствующие биты (1, 2, 3) в 1.

Формат слова состояния канала напоминает формат регистра управляющего слова, за исключением двух старших разрядов 7 и 6:

7 6 5 4 3 2 1 0
T-T-T-T-T-T-T-¬
¦ ¦ ¦ ¦ ¦ ¦
LT+T+T+T+T+-+T+T-
¦ ¦ LT- L=T=- L= BCD: 0 - двоичный счет;
¦ ¦ ¦ ¦ 1 - двоично-десятичный счет.
¦ ¦ ¦ ¦
¦ ¦ ¦ L===== M: 000 - режим 0;
¦ ¦ ¦ 001 - режим 1;
¦ ¦ ¦ X10 - режим 2;
¦ ¦ ¦ X11 - режим 3;
¦ ¦ ¦ 100 - режим 4;
¦ ¦ ¦ 101 - режим 5.
¦ ¦ ¦
¦ ¦ L========== RW: 00 - код команды CLC (запомнить CE);
¦ ¦ 01 - чтение/запись старшего байта;
¦ ¦ 10 - чтение/запись младшего байта;
¦ ¦ 11 - чтение/запись младшего, затем
¦ ¦ старшего байта.
¦ ¦
¦ L============= FN: флаг перезагрузки констант;
L=============== OUT: состояние выхода OUT.

Разряд FN используется, в основном, в режимах 1 и 5 для определения, произошла ли загрузка константы из регистра CR в регистр счетчика CE.

Разряд OUT позволяет определить состояние выходной линии канала OUT в момент выполнения команды RBC.

Для программирования канала таймера необходимо выполнить следующую последовательность действий:

вывести в порт управляющего регистра с адресом 43h управляющее слово;
требуемое значение счетчика посылается в порт канала (адреса 40h. 42h), причем вначале выводится младший, а затем старший байты значения счетчика.
Сразу после этого канал таймера начнет выполнять требуемую функцию.

Для чтения текущего содержимого счетчика CE необходимо выполнить следующее:

вывести в порт управляющего регистра код команды CLC (команда запоминания содержимого регистра CE);
вывести в порт управляющего регистра код команды запроса на чтение/запись в регистры канала (поле RW должно содержать 11);
двумя последовательными командами ввода из порта нужного канала ввести младший и старший байты текущего сосотояния счетчика CE.
Для чего вам может понадобиться перепрограммирование каналов таймера?

Если вам надо повысить точность измерения времени, выполняемого с помощью канала 0 таймера, вы можете увеличить частоту генерируемых этим каналом импульсов (стандартно 18,2 Гц). По окончании измерений режим работы канала необходимо восстановить для правильного функционирования системы.

Помогите пожалуйста на любом примере.

Не понимаю как привязать к тику таймера процедуру. Буду благодарен любым примерам.

1 ответ 1


Спасибо вам за ответ, но этот способ не работает если используется system.windows.forms . Мне удалось создать и запустить таймер с помощью var t1:= new system.Windows.Forms.Timer; Но как привязать к нему процедуру - не понимаю.

Похожие

Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

дизайн сайта / логотип © 2022 Stack Exchange Inc; материалы пользователей предоставляются на условиях лицензии cc by-sa. rev 2022.1.28.41306

Репутация: нет
Всего: 32

Собственно, можно ли сделать подобие таймера в Паскале (может с Ассемблером), чтоб каждые две секунды выполнялось какое-нибудь действие, а в промежутке пользователь мог клацать по клавиатуре и мышке?

Репутация: 2
Всего: 71

В паскале с таймерами полный гемор. Я как то делал такое, только исходников не осталось.
Сначала узнавай в таблице векторов прерываний адрес текущей функции прерывания таймера:

Код

var LastTimer:pointer;
GetIntVec($1C,LastTimer);

потом изменяй таблицу прерываний
Код

SetIntVec($1C,addr(NewTimer));

NеwTimer - это заранее определенная процедура
Код


procedure NewTimer; interrupt;
begin

end;


И усё, вот и таймер. Только по окончании работы восстанови таблицу векторов прерываний:
Код

SetIntVec($1C,LastTimer);

Не забудь подключить CRT и DOS
Не проверял, но работать вроде должно.

Репутация: нет
Всего: 32

Perchilla Получается, NewTimer - это процедура типа события OnTimer?
И еще:
Цитата
потом изменяй таблицу прерываний

это когда? чет я не понял.
А ты не мог бы на примере? Если не сложно.

Репутация: 2
Всего: 71

Пример не могу, потому что работать не будет. Паскаль я уже порядком подзабыл. Просто выделил для тебя основные моменты:
1. Наличие обработчика прерываний: procedure NewTimer; interrupt;
2. Сохранение таблицы векторов прерываний GetIntVec($1C,LastTimer);
3. Изменение таблицы векторов прерываний: SetIntVec($1C,addr(NewTimer));
4. Восстановление таблицы векторов прерываний: SetIntVec($1C,LastTimer);

$1C соответствует прерыванию от таймера;

Тут в обработчике еще должна быть фильтрация прерываний, чтобы не каждое прерывание обрабатывалось, но это я уже не помню.

Читайте также: