Vecctors.PAS

{* Использование COM-порта как таймера под Win *}

Unit VECCTORS;
Interface
Implementation
Begin
 writeln('Программирование портов и таймера RS-232 для формирования и обработки прерываний от СОМ-порта синхронизированных по времени ');
End.

Program pas97124;

Uses Vecctors.pas; {* Эту строку можно удалить *}
unit Vectors; {====}
interface   {=====}
Uses WinTypes, WinProcs, WinDos, Messages; {* Вызов внешних функций *}
Var {* В работе нам потребуются переменные: *}
  Old_Vec0B                       : Pointer; {== для запоминания старого вектора ==}
  H_Module                        : tHandle; {== модуль, которому будут посылаться }
  {== квантованные сообщения          ==}
  { = H_Module := GetCurrentTask;
  - внизу в секции инициализации = }

  {== сообщения из обработчика прерываний ==}
Function SetMyVector(  Nom_Vec  : Byte; {= номер вектора Intr         ==}
New_Vector                      : Pointer; {= ук-ль на новый обработчик  ==}
)                               : Pointer; {== возвращает старый вектор         ==}
Procedure SetOldVector( Nom_Vec : Byte;
Old_Vec                         : Pointer); {===}
{===}
{$IFDEF COM1}
{$
Else }

  {$EndIF} {==================  Собственно обработчик прерываний  ====================}
Var {* В работе нам потребуются переменные: *}
  j                                 : Byte;
  nkan                              : Word;
Begin
  j := Port[Baze_Port + $0D]; {== сбросить регистр прерываний       ==}
  j := Port[Baze_Port + $08]; {== сбросить регистр данных           ==}
  Port[Baze_Port + $08] := $55; {== снова "зарядить" "прерыватель"    ==}
  {== передать сообщение            ==}
  Port[$20] := $20; {== сбросить контроллер прерываний    ==}
  { == Handler == }
  {== Инициализация COMa, программирование маски и установка вектора ========}
  Function SetMyVector( New_Handler : Pointer);
  Var {* Объявление переменных *}
    i       : Byte;
    j       : Byte;
    Old_Vec : Pointer;
  Const {* Постоянные значения *}
    Divider = 57; {== задать требуемую величину делителя таймера COMa ==}
    Begin
      Port[Baze_Port + $0B] := Port[Baze_Port + $0B] Or $80; {== DLAB := 1 ==}
      PortW[Baze_Port + $08] := Divider; { = = 57 - 5 msec;
      23 - 5000 бод (2мсек) = = }

      ^    Port[Baze_Port + $0B] := Port[Baze_Port + $0B] And $7F; {== DLAB := 0 ==}
      Port[Baze_Port + $0b] := $03; {== 8бит, 1стоп, без контр ==}
      i := Port[Baze_Port + $08];
      asm cli
    End;
    GetIntVec(Nom_Vec, Old_Vec); {==  сохранить старый адрес===}
    SetIntVec(Nom_Vec, New_Vector); {==  установить адрес п/п  ===}
    i := Port[$21];
    Port[$21] := (i Or $18); {==  установить маску          ===}
    Port[$21] := Port[$21] And $E7;
    Port[Baze_Port + $0B] := Port[Baze_Port + $0B] And $7F;
    Port[Baze_Port + $09] := 1; {==  разрешить прерывания от СОМа   ===}
    i := Port[Baze_Port + $0E]; {==  сброс прерывания от модема      ==}
    Port[Baze_Port + $0C] := $0B;
    SetMyVector := Old_Vec;
    asm sti
End;
  Port[Baze_Port + $08] := $AA; {== сразу зарядить "прерыватель" ==}
  End{ SetMyVector }
  {========= Восстановить старый обработчик ============================}
Procedure SetOldVector( Nom_Vec : Byte;
Old_Vec : Pointer);
Begin
asm cli
End;
SetIntVec(Nom_Vec, Old_Vec);
asm sti
End;

End{===========}
initialization   {==========}
h_Module := GetCurrentTask;
End....