{ Контроллер ПНЧ (АК9)} unit MI1201AGM_CVF_Emulator; interface USES {$IfNDef Seg16}SysUtils,{$EndIf} TimeInterval_Emulator, Peak_Emulator, MI1201AGM_Hardware_Emulator, MI1201AGM_Controller_Emulator; const cDataSignature='CVF emulator data. '^M^L; cRegistrySubPath='CVF'; cValidPorts=[$60..$7F]; cValidReadPorts=cValidPorts-[$78]; cValidWritePorts=cValidPorts; cDataChl1Words=[$63, $67]; cDataChl2Words=[$62, $66]; cDataChl3Words=[$61, $65]; cDataChl4Words=[$6B, $6F]; cDataChl5Words=[$6A, $6E]; cDataChl6Words=[$69, $6D]; cDataChl7Words=[$73, $77]; cDataChl8Words=[$72, $76]; cDataChl9Words=[$71, $75]; cDataLoWords=[$61..$63, $69..$6B, $71..$73]; cDataHiWords=[$65..$67, $6D..$6F, $75..$77]; cDataAll=cDataLoWords+cDataHiWords; type tDataSignature=array[1..Length(cDataSignature)] of char; tChannel=0..9; tChannels= set of tChannel; tCtrlPort=1..6; tDataPort=1..18; tFlag=(fTriggerReset, fGate, fReadyToStart, fTimetCtrlWordOK); tFlags=set of tFlag; tCtrlByteCounter=0..1; tCtrlPortCounter=0..2; tDataByteCounter=0..3; tDataWordCounter=0..1; tWord=record case byte of 0:(w:word;); 1:(b:array[tCtrlByteCounter] of byte); end; type tCounterArray=array[tDataWordCounter] of tDataByteCounter; tCounter=record Read, Write:tCounterArray; end; tTimerData=record Counter:tCtrlByteCounter; Time:tWord; end; const cCounter0:tCounter=(Read:(0,0); Write:(0,0)); type tCounterDataArray=array[tDataByteCounter] of Byte; tCounterData=record Counter:tCounter; case byte of 0:(WW:array[tDataWordCounter] of tWord); 1:(BB:array[tDataByteCounter] of byte); end; tCtrlData=record CtrlByteCounter:tCtrlByteCounter; CtrlWord:tWord; end; tSignalBytes=array[tDataByteCounter] of Byte; tCtrlsData=array[tChannel] of tCtrlData; tCountersData=array[tChannel] of tCounterData; // Данные, сохраняющиеся между измерениями tData=record Signature:tDataSignature; Flags:tFlags; Time:tTime_MS; Channels:tCtrlsData; ChannelsData:tCountersData; ActiveChannels:tChannels; TimerData:tTimerData; TimeScaleCoeff:word; end; // Данные, НЕсохраняющиеся между измерениями tTmpData=record end; tError=( eCvfOK, eCvfTimer0, eCvfTimer1, ecvfNotReadyToStart, eCvfInvalidTimetCtrlWord, ecvfDoOutDataWord, ecvfInvalidOutDataWord, ecvfNotTriggerReset, eInvalidPort, eReadFromInvalidPort, eWriteToInvalidPort ); resourcestring rsECvfOK='OK'; rsECvfTimer0='Ошибка таймера 0'; rsECvfTimer1='Ошибка таймера 1'; rsECvfNotReadyToStart='Таймер не готов к запуску'; rseCvfInvalidTimetCtrlWord='неверное слово управления таймера'; rsECvfDoOutDataWord='Запись вперемешку с чтением в порты данных счетчика'; rsECvfInvalidOutDataWord='Неверный вывод в порты данных счетчика'; rsECvfNotTriggerReset='Сброс триггера не произведен'; rseCvfInvalidPort='неверный порт'; rseCvfReadFromInvalidPort='чтение из неверного порта'; rseCvfWriteToInvalidPort='запись в неверный порт'; const cCFVErrorMsgs:array[tError] of string=( rsECvfOK, rsECvfTimer0, rsECvfTimer1, rsECvfNotReadyToStart, rseCvfInvalidTimetCtrlWord, rsECvfDoOutDataWord, rsECvfInvalidOutDataWord, rsECvfNotTriggerReset, rseCvfInvalidPort, rseCvfReadFromInvalidPort, rseCvfWriteToInvalidPort ); type tCVF=class(tController) private prData:tData; prTimer0,prTimer1:tTimerMI1201X; prTmpData:tTmpData; procedure InitChannels; procedure Start; function TriggerReset:byte; function Gate:byte; function CheckCtrlWord(c:tChannel):boolean; function CheckAllCtrlWords:tChannel; procedure OutCtrlWord(b:byte; port:word); function CheckDataWord(c:tChannel):boolean; function CheckAllDataWords:tChannel; procedure OutDataWord(b:byte; port:word); function DataByteGet(port:word):byte; procedure DoOutDataWord(cl:tChannel; LoHi:tDataWordCounter; b:byte); function ReadyToStart:boolean; procedure OutTimerCtrlWord(b:byte); function InProgress:byte; procedure TimerError(Sender:tObject); protected // обязательные процедуры function SubPath:string; override; procedure prOutByte(b:Byte; port:word); override; function prInByte(port:word):Byte; override; function CheckData(Data:pointer):boolean; override; function DataSize:integer; override; function SetData(aData:pointer):boolean; override; function GetData(aData:pointer):boolean; override; // прочие процедуры function GetErrorMsgs(AError:cardinal):string; override; public // обязательные процедуры constructor Create(Hardware:tMi1201HardwareEmulator); destructor Destroy; override; procedure ReInit; override; procedure SetDefaultData; override; function ValidPort(APort:word):boolean; function ValidReadPort(APort:word):boolean; function ValidWritePort(APort:word):boolean; // прочие процедуры end; implementation function tCVF.GetErrorMsgs(AError:cardinal):string; begin if AError<=Ord(High(tError)) then begin Result:=cCFVErrorMsgs[tError(AError)]; end else begin Result:=Inherited GetErrorMsgs(AError); end; end; procedure tCVF.TimerError(Sender:tObject); begin if Sender=prTimer0 then ErrorCode:=Ord(eCvfTimer0) else if Sender=prTimer1 then ErrorCode:=Ord(eCvfTimer1); end; function tCVF.SetData(aData:pointer):boolean; begin Result:=Inherited SetData(aData); if Result then begin Inc(Cardinal(aData),Inherited DataSize); Result:=CheckData(aData); if Result then begin Move(aData^,prData,DataSize); end; end; end; function tCVF.GetData(aData:pointer):boolean; begin Result:=Inherited GetData(aData); if Result then begin Inc(Cardinal(aData),Inherited DataSize); Result:=CheckData(aData); if Result then begin Move(prData,aData^,SizeOf(prData)); end; end; end; function tCVF.DataSize:integer; begin Result:=Inherited DataSize + SizeOf(prData); end; function tCVF.SubPath:string; begin Result:=cRegistrySubPath; end; function tCVF.CheckData(Data:pointer):boolean; begin Result:=Inherited CheckData(Data) and TRUE; end; constructor tCVF.Create(Hardware:tMi1201HardwareEmulator); begin prTimer0:=tTimerMI1201X.Create; prTimer1:=tTimerMI1201X.Create; prTimer0.OnError:=TimerError; prTimer1.OnError:=TimerError; Inherited; end; destructor tCVF.Destroy; begin Inherited; prTimer0.Free; prTimer1.Free; end; procedure tCVF.ReInit; begin end; procedure tCVF.SetDefaultData; begin prData.Signature:=cDataSignature; prData.Flags:=[]; prTimer0.Clear; prTimer1.Clear; prData.Time:=GetTickCount; prData.ActiveChannels:=[1..9]; prData.TimerData.Counter:=0; prData.TimerData.Time.W:=0; InitChannels; prData.TimeScaleCoeff:=1; ErrorCode:=Ord(eCvfOK); end; procedure tCVF.InitChannels; var i:tChannel; begin for i:=Low(i) to High(i) do begin with prData.Channels[i] do begin CtrlWord.W:=0; CtrlByteCounter:=0; end; end; for i:=Low(i) to High(i) do begin with prData.ChannelsData[i] do begin WW[0].W:=0; WW[1].W:=0; Counter:=cCounter0; end; end; end; function tCVF.CheckCtrlWord(c:tChannel):boolean; begin case c of 1,4,7: Result:=prData.Channels[c].CtrlWord.w=$3434; 2,5,8: Result:=prData.Channels[c].CtrlWord.w=$7474; 3,6,9: Result:=prData.Channels[c].CtrlWord.w=$B4B4; else Result:=FALSE; end; end; function tCVF.CheckAllCtrlWords:tChannel; var i:tChannel; begin for i:=Succ(Low(i)) to High(i) do if i in prData.ActiveChannels then begin if not CheckCtrlWord(i) then begin CheckAllCtrlWords:=i; Exit; end; end; CheckAllCtrlWords:=0; end; function tCVF.CheckDataWord(c:tChannel):boolean; begin CheckDataWord:=(prData.ChannelsData[c].WW[0].w=$FFFF) and (prData.ChannelsData[c].WW[1].w=$FFFF); end; function tCVF.CheckAllDataWords:tChannel; var i:tChannel; begin for i:=Succ(Low(i)) to High(i) do if i in prData.ActiveChannels then begin if not CheckDataWord(i) then begin CheckAllDataWords:=i; Exit; end; end; CheckAllDataWords:=0; end; function Port2CtrlByteNum(port:word):tCtrlByteCounter; begin case port of {owLo123:}$60, {owLo456:}$68, {owLo789:}$70:begin Result:=0; end; {owHi123:}$64, {owHi456:}$6C, {owHi789:}$74:begin Result:=1 end; else begin Result:=0; RunError(201); end; end; end; function Byte2CtrlChannel(b:byte; port:word):tChannel; var cl:tChannel; begin case b of $34:cl:=1; $74:cl:=2; $B4:cl:=3; else begin cl:=0; RunError(201); end; end; case port of $60,$64: ; $68,$6C: Inc(cl,3); $70,$74: Inc(cl,6); else begin RunError(201); end; end; Byte2CtrlChannel:=cl; end; procedure tCVF.OutCtrlWord(b:byte; port:word); begin prData.Channels[Byte2CtrlChannel(b,port)].CtrlWord.b[Port2CtrlByteNum(port)]:=b; end; procedure tCVF.DoOutDataWord(cl:tChannel; LoHi:tDataWordCounter; b:byte); begin with prData.ChannelsData[cl] do begin if Counter.Read[LoHi]<>Low(Counter.Read[LoHi]) then begin ErrorCode:=Ord(ecvfDoOutDataWord); end; WW[LoHi].b[Counter.Write[LoHi]]:=$FF; if Counter.Write[LoHi]=High(Counter.Write[LoHi]) then Counter.Write[LoHi]:=Low(Counter.Write[LoHi]) else Inc(Counter.Write[LoHi]); end; end; function Port2Channel(port:word):tChannel; begin case port of {rwLo1:}$63, {rwHi1:}$67: begin Port2Channel:=1; end; {rwLo2:}$62, {rwHi2:}$66: begin Port2Channel:=2; end; {rwLo3:}$61, {rwHi3:}$65: begin Port2Channel:=3; end; {rwLo4:}$6B, {rwHi4:}$6F: begin Port2Channel:=4; end; {rwLo5:}$6A, {rwHi5:}$6E: begin Port2Channel:=5; end; {rwLo6:}$69, {rwHi6:}$6D: begin Port2Channel:=6; end; {rwLo7:}$73, {rwHi7:}$77: begin Port2Channel:=7; end; {rwLo8:}$72, {rwHi8:}$76: begin Port2Channel:=8; end; {rwLo9:}$71, {rwHi9:}$75: begin Port2Channel:=9; end; else begin Result:=0; RunError(201); end; end; end; function Port2WordNum(port:word):tDataWordCounter; begin case port of $61..$63, $69..$6B, $71..$73: begin Result:=0; end; $65..$67,$6D..$6F,$75..$77: begin Result:=1; end; else begin Result:=0; RunError(201); end; end; end; function Channel2UPT(cl:tChannel):tUPT; begin Channel2UPT:=tUpt(cl); end; function tCVF.DataByteGet(port:word):byte; var cl:tChannel; wn:tDataWordCounter; s:tSignal; begin cl:=Port2Channel(port); if CheckCtrlWord(cl) and CheckDataWord(cl) then begin wn:=Port2WordNum(port); with prData.ChannelsData[cl] do begin if cl=0 then s:=0 else s:=Hardware.UPTSignal(Channel2UPT(Pred(cl))); s:=s*prData.TimeScaleCoeff*prTimer0.Elapsed; DataByteGet:=tSignalBytes(s)[Counter.Read[wn]] end; end else begin DataByteGet:=$FF; end; end; procedure tCVF.OutDataWord(b:byte; port:word); begin DoOutDataWord(Port2Channel(port),Port2WordNum(port),b); if b<>$FF then ErrorCode:=Ord(ecvfInvalidOutDataWord); end; function tCVF.TriggerReset:byte; begin Include(prData.Flags,fTriggerReset); Exclude(prData.Flags,fGate); Exclude(prData.Flags,fReadyToStart); InitChannels; TriggerReset:=$0; end; function tCVF.Gate:byte; begin Include(prData.Flags,fGate); Gate:=$0; end; function tCVF.ReadyToStart:boolean; begin if (fReadyToStart in prData.Flags) then begin ReadyToStart:=TRUE; end else if (fTriggerReset in prData.Flags) and (fGate in prData.Flags) and (fTimetCtrlWordOK in prData.Flags) and prTimer0.ReadyToStart and (CheckAllCtrlWords=0) and (CheckAllDataWords=0) then begin Include(prData.Flags,fReadyToStart); ReadyToStart:=TRUE; end else begin ReadyToStart:=FALSE; end; end; procedure tCVF.OutTimerCtrlWord(b:byte); begin if b=$32 then begin Include(prData.Flags,fTimetCtrlWordOK); end else begin ErrorCode:=Ord(eCvfInvalidTimetCtrlWord); end; end; procedure tCVF.Start; begin if ReadyToStart then begin prTimer0.Start; end else begin ErrorCode:=Ord(ecvfNotReadyToStart); end; end; function tCVF.InProgress:byte; begin if prTimer0.Expired then InProgress:=0 else InProgress:=1; end; procedure tCVF.prOutByte(b:Byte; port:word); begin port:=port and $FF; if not (fTriggerReset in prData.Flags) then ErrorCode:=Ord(ecvfNotTriggerReset); case port of $7C:begin {Включение счета, подг. контроллером} Start; end; $60,$64,$68,$6C,$70,$74: begin { Порты записи управляющих слов в каналы счета ¦ (для двух младших и двух старших байтов)} OutCtrlWord(b, port); end; $61..$63,$65..$67, $69..$6B,$6D..$6F, $71..$73,$75..$77: begin{ Порты чтения/записи информации счета контроллера ¦ (для двух младших и двух старших байтов)} OutDataWord(b, port); end; $78: begin OutTimerCtrlWord(b); end; $7A:begin {запись содерж. 1 канала D21 } prTimer1.OutTime(b); end; $7B: begin {запись содерж. 0 канала D21 } prTimer0.OutTime(b); end; $7D: begin { Сброс схемы прерывания (D17.2) Установка сигнала GATE для микросхем:D2,D8,D10,D14,D19,D27 (каналы счета)} Gate; end; $7E: begin {Управление реле блока ПНЧ} Hardware.PNCReleSet(tPNCReleSet(b)); end; else if port in cValidReadPorts then begin WriteToInvalidPort:=TRUE; ErrorCode:=Ord(eWriteToInvalidPort); end else begin InvalidPort:=TRUE; ErrorCode:=Ord(eInvalidPort); end; end; end; function tCVF.prInByte(port:word):Byte; begin port:=port and $FF; Result:=$FF; case port of $61..$63,$65..$67, $69..$6B,$6D..$6F, $71..$73,$75..$77: begin{ Порты чтения/записи информации счета контроллера ¦ (для двух младших и двух старших байтов)} Result:=DataByteGet(port); end; $7A:begin {чтение содерж. 1 канала D21 } Result:=prTimer1.InTime; end; $7B: begin {чтение содерж. 0 канала D21 } Result:=prTimer0.InTime; end; $7C:begin { Сброс контроллера } Result:=TriggerReset; end; $7E: begin {Управление реле блока ПНЧ} Result:=Byte(Hardware.PNCRele); end; $7F: begin { Чтение готовности } Result:=InProgress; end; else if port in cValidWritePorts then begin ReadFromInvalidPort:=TRUE; ErrorCode:=Ord(eReadFromInvalidPort); end else begin InvalidPort:=TRUE; ErrorCode:=Ord(eInvalidPort); end; end; end; function tCVF.ValidPort(APort:word):boolean; begin Result:= ((APort and $FF00)=cBasePort) and ((APort and $FF) in cValidPorts); end; function tCVF.ValidReadPort(APort:word):boolean; begin Result:= ((APort and $FF00)=cBasePort) and ((APort and $FF) in cValidReadPorts); end; function tCVF.ValidWritePort(APort:word):boolean; begin Result:= ((APort and $FF00)=cBasePort) and((APort and $FF) in cValidWritePorts); end; end. { Контроллер ПНЧ (АК9) г========T================T=====================================¬ ¦ Адрес ¦ ПОРТ ¦ ¦ ¦ порта +-------T--------+ Назначение ¦ ¦ ¦чтение ¦запись ¦ ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ Порты записи управляющих слов в каналы счета ¦ ¦ (для двух младших и двух старших байтов) ¦ ¦--------T-------T--------T-------------------------------------¦ ¦ $60 ¦ - ¦ + ¦1 канал: два мл. байта (Упр.сл.=$34) ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $64 ¦ - ¦ + ¦1 канал: два ст. байта (Упр.сл.=$34) ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $60 ¦ - ¦ + ¦2 канал: два мл. байта (Упр.сл.=$74) ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $64 ¦ - ¦ + ¦2 канал: два ст. байта (Упр.сл.=$74) ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $68 ¦ - ¦ + ¦4 канал: два мл. байта (Упр.сл.=$34) ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $6C ¦ - ¦ + ¦4 канал: два ст. байта (Упр.сл.=$34) ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $68 ¦ - ¦ + ¦5 канал: два мл. байта (Упр.сл.=$74) ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $6C ¦ - ¦ + ¦5 канал: два ст. байта (Упр.сл.=$74) ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $68 ¦ - ¦ + ¦6 канал: два мл. байта (Упр.сл.=$B4) ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $6С ¦ - ¦ + ¦6 канал: два ст. байта (Упр.сл.=$B4) ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $60 ¦ - ¦ + ¦3 канал: два мл. байта (Упр.сл.=$B4) ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $64 ¦ - ¦ + ¦3 канал: два ст. байта (Упр.сл.=$B4) ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $70 ¦ - ¦ + ¦7 канал: два мл. байта (Упр.сл.=$34) ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $74 ¦ - ¦ + ¦7 канал: два ст. байта (Упр.сл.=$34) ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $70 ¦ - ¦ + ¦8 канал: два мл. байта (Упр.сл.=$74) ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $74 ¦ - ¦ + ¦8 канал: два ст. байта (Упр.сл.=$74) ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $70 ¦ - ¦ + ¦9 канал: два мл. байта (Упр.сл.=$B4) ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $74 ¦ - ¦ + ¦9 канал: два ст. байта (Упр.сл.=$B4) ¦ L--------+-------+--------+-------------------------------------- г---------------------------------------------------------------¬ ¦ Порты для управления режимами работы контроллера ПНЧ ¦ ¦--------T-------T--------T-------------------------------------¦ ¦ $7C ¦ - ¦ + ¦Включение счета, подг. контроллером ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $7C ¦ + ¦ - ¦ Сброс контроллера ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $7D ¦ - ¦ + ¦Установка сигнала GATE для микросхем:¦ ¦ ¦ ¦ ¦D2,D8,D10,D14,D19,D27 (каналы счета) ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $7D ¦ - ¦ + ¦Сброс схемы прерывания (D17.2) ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $7E ¦ - ¦ + ¦Управление режимом блока ПНЧ ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $7F ¦ - ¦ + ¦Для досчета импульсов в каналы счета ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $7F ¦ + ¦ - ¦Чтение готовности ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ Порты управления таймером (D21) ¦ ¦--------T-------T--------T-------------------------------------¦ ¦ $78 ¦ - ¦ + ¦Запись управляющего слова для таймера¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $7A ¦ + ¦ + ¦Чтение/запись содерж. 1 канала D21 ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $7B ¦ + ¦ + ¦Чтение/запись содерж. 0 канала D21 ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ Порты чтения/записи информации счета контроллера ¦ ¦ (для двух младших и двух старших байтов) ¦ ¦--------T-------T--------T-------------------------------------¦ ¦ $63 ¦ + ¦ + ¦ 1-й канал: два младших байта ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $67 ¦ + ¦ + ¦ 1-й канал: два старших байта ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $62 ¦ + ¦ + ¦ 2-й канал: два младших байта ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $66 ¦ + ¦ + ¦ 2-й канал: два старших байта ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $6B ¦ + ¦ + ¦ 4-й канал: два младших байта ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $6F ¦ + ¦ + ¦ 4-й канал: два старших байта ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $6A ¦ + ¦ + ¦ 5-й канал: два младших байта ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $6E ¦ + ¦ + ¦ 5-й канал: два старших байта ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $69 ¦ + ¦ + ¦ 6-й канал: два младших байта ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $6D ¦ + ¦ + ¦ 6-й канал: два старших байта ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $61 ¦ + ¦ + ¦ 3-й канал: два младших байта ¦ L--------+-------+--------+-------------------------------------- г--------T-------T--------T-------------------------------------¬ ¦ $65 ¦ + ¦ + ¦ 3-й канал: два старших байта ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $73 ¦ + ¦ + ¦ 7-й канал: два младших байта ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $77 ¦ + ¦ + ¦ 7-й канал: два старших байта ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $72 ¦ + ¦ + ¦ 8-й канал: два младших байта ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $76 ¦ + ¦ + ¦ 8-й канал: два младших байта ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $71 ¦ + ¦ + ¦ 9-й канал: два младших байта ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $75 ¦ + ¦ + ¦ 9-й канал: два старших байта ¦ L========¦=======¦========¦=====================================- Порядок работы В начале программы сбросить триггер командой чтения порта $7C: A:=Port($60+$1C) 1) Включить нужный канал измерения (если он не включен) командой записи в порт $7E: Port($60+$1E):=K где K - номер канала (1 .. 9) 2) Записать во все 9 каналов управляющие слов; 3) Записать во все 9 каналов $FF в младшие и старшие 2 байта (двойное обращение) 4) Записать управляющее слово в таймер командой: Port($60+$18):=$32 5) Записать время интегрирования в 0-й канал таймера командой: Port($60+$1B):=мл. байт Port($60+$1B):=ст. байт 6) Установить "GATE" в "1" командой: Port($60+$1D):=0 7) Досчитать 2 импульса командами: Port($60+$1F):=0 Port($60+$1F):=0 8) Включить счет: Port($60+$1C):=0 9) Окончание счета контролировать по появлению "-¬ " перепада L- 0 бита при чтении порта ($60+$1F) - это можно будет сделать по прерыванию; 10) По окончании счета сосчитать содержимое нужных каналов счетчиков и подсчитать количество сосчитанных импульсов по формуле: N:=(65535*65535-Nст.1+Nст.2*256))+(65535-(Nмл.1+Nмл.2*256)))/t , где Nст.1 - младший (первый) байт старшего счетчика Nст.2 - старший (второй) байт старшего счетчика Nмл.1 - младший (первый) байт младшего счетчика Nмл.2 - старший (первый) байт младшего счетчика t - время интегрирования в сек. Для большей скорости обмена можно п. 2,3,4,5 выполнить один раз в начале измерений, а не выполнять каждый раз. Однако в этом случае возрастает риск сбоев при случайной потере управ- ляющих слов или информации микросхемами ВИ53. Управление реле блока ПНЧ осуществляется командой записи в порт [$60+$1E] кода реле (0..15) из следующей таблицы: г=====T============================T=====================¬ ¦ N ¦ ¦ Значение бита ¦ ¦ ¦ Назначение бита +----------T----------¦ ¦бита ¦ ¦ 0 ¦ 1 ¦ ¦-----+----------------------------+----------+----------¦ ¦ ¦ Управляет шиной опорного ¦На шину ¦На шину ¦ ¦ 0 ¦ напряжения, идущей на входы¦опоры по- ¦опоры по- ¦ ¦ ¦ ЦВ и ПНЧ при калибровке ¦дано -9 V ¦дано 0 V ¦ ¦-----+----------------------------+----------+----------¦ ¦ ¦ ¦На вход ¦На вход ¦ ¦ ¦ ¦ПНЧ под- ¦ПНЧ подан ¦ ¦ 1 ¦ Управляет входами ПНЧ ¦ключена ¦сигнал с ¦ ¦ ¦ ¦шина опоры¦ЭМУ ¦ ¦-----+----------------------------+----------+----------¦ ¦ ¦ Инвертирует сигнал 3 канала¦Сигнал ¦Сигнал не ¦ ¦ 2 ¦(для МИ1201 АГ) или ВЭУ (для¦инвертиру-¦инвертиру-¦ ¦ ¦МИ1201 ИГ) ¦ется ¦ется ¦ L=====¦============================¦==========¦==========- ПРИМЕРЫ: 1) $04 - на вход ПНЧ идет напряжение опоры -9 V 2) $05 - на вход ПНЧ идет напряжение опоры 0 V 3) $06 - на вход ПНЧ идет напряжение с ЭМУ 4) $02 - на вход ПНЧ идет напряжение с ЭМУ, а 3-й канал - ВЭУ }