{ Контроллер пульта управления 5.105.184 (АК-3) } {--------------------------------------------------------------------------- The control units for mass-spectrometer MI1201-AGM (c) Copyright Aleksandrov O.E., 1998 Модуль управления масс-спектрометром МИ1201-АГМ (c) Собственность Александрова О.Е., 1998 Molecular Physics department 620002, Екатеринбург, К-2 USTU, Ekaterinsburg, K-2, 620002 УГТУ, RUSSIA Кафедра молекулярной физики phone 75-48-39 тел. 75-48-39 E-mail: aleks@dpt.ustu.ru ----------------------------------------------------------------------------} Unit c_Panel; INTERFACE USES MITypes, c_Ctrl, c_Ctrl1, c_Bus; const cSwitchDelay=500; {(мс), Задержка повторного переключения блоков, иначе при быстром повторном вызове не успевают срабатывать реле} ckV2SEM_koeff=94880; {коэффициент преобразования числа из ЦАП ВЭУ в Вольты } ckV2SEM_Scale=100000; {масштаб преобразования числа из ЦАП ВЭУ в Вольты } cMinSEM_U=0; { В максимальное напряжение на ВЭУ } cMaxSEM_U=5000; { В максимальное напряжение на ВЭУ } type { Коды ошибок } tErrorCodes=({$I C_ErrCds.Inc}, ecFailBlocks, ecFailCurBlocks, { ecBadBlocksCombination,} ecFailSource, ecFailInOut, ecFailValves, ecFailCurValves, ecFailValvesControlEnable, ecFailCurValvesControlEnable, ecFailWriteSEM, ecFailReadSEM, ecBadControllerState); tFlag=(fSkipValvesClosingOnExInit, fSkipValvesClosingOnExDone, fValvesRestoreOnExInit,fBlocksRestoreOnExInit); tFlags=set of tFlag; tTmpFlag=(fDone); tTmpFlags=set of tTmpFlag; { флаги блоков } tBlock=(fBPGI, f10kV, fSEM, fValvesControl, fb4, fb5, fb6, fb7); tBlocks=set of tBlock; { флаги клапанов } tValve=(fS0, fS1, fS2, vfVX, fLine2Out, fLine2In, fLine1Out, fLine1In); tValves=set of tValve; tSEMData=0..$FFF; tSEMVoltage=cMinSEM_U..cMaxSEM_U; tPort=(rwSEMDACLowByte,rwSEMDACUpByte_SEMCode,rwBlocks,rwValves); tPortsArray=array[tPort] of Byte; const cUnreadablePorts=[]; type tPorts=record case byte of 0:(rwSEMDACLowByte, rwSEMDACUpByte_SEMCode, rwBlocks, rwValves:word); 1:(Ports:array[tPort] of word); end; tData=record Ports:tPorts; Flags:tFlags; SEM_coeff:longint; PortsData:tPortsArray; BlocksSwitchTimeOut:word; BlocksSwitchTimeOutResolution:word; LastBlocks:tBlocks; LastSEM:tSEMVoltage; LastValves:tValves; // LastSEM_Value:tSEMVoltage; end; tTmpData=record Flags:tTmpFlags; LastValvesSwitchTime:tTiks; end; tCtrl=object(c_Ctrl1.tCtrl) function Name:tName; virtual; { НЕисполняемые функции (без ввода/вывода в порты)} constructor InitDefault(var Bus:c_Bus.tCtrl); constructor Init(var Bus:c_Bus.tCtrl; Ports:tPorts); destructor Done; function ErrorMessage(en:tErrorCode):string; virtual; procedure SetNoError; virtual; function BlocksSwitchTimeOut:word; procedure BlocksSwitchTimeOutSet(x:word); function BlocksSwitchTimeOutResolution:word; function Flags:tFlags; function FlagSet(AFlag:tFlag; AState:boolean):boolean; function FlagState(AFlag:tFlag):boolean; { function ValvesClosingOnExDone:boolean; procedure ValvesClosingOnExDoneSet(x:boolean); function ValvesClosingOnExInit:boolean; procedure ValvesClosingOnExInitSet(x:boolean); function ValvesRestoreOnExInit:boolean; procedure ValvesRestoreOnExInitSet(x:boolean);} { Данные ЦАП ВЭУ } procedure SEMCoeffSet(x:longint); { коэффициент преобразования Вольты->ЦАП_ВЭУ ЦАП_ВЭУ=SEMCoeff*Вольты} function SEMCoeff:longint; function SEMMax:word; function SEMMin:word; function SEMStep:word; function SEMCountMax:word; function SEMCount:word; { Исполняемые функции (ввод/вывод в порты)} procedure exInit; virtual; procedure exBlocksONSet(x:tBlocks); function exBlockONSet(x:tBlock):boolean; function exBlockOffSet(x:tBlock):boolean; procedure exSourceSet(x:tSource); procedure exInOutOpenSet(x:tValves); procedure exBlocksOnGet(var x:tBlocks); function exBlockONGet(x:tBlock):boolean; function exValvesControlEnable:boolean; function exSource:tSource; procedure exInOutOpenGet(var x:tValves); { Сохранение/восстановление состояния контроллера } function DataSize:word; function Restore(var DataPtr:pointer):boolean; function Save(var DataPtr:pointer):boolean; { Данные ЦАП ВЭУ } procedure exSEM_ValueSet(x:tSEMVoltage);{ установка данных в вольтах } function exSEM_Value:tSEMVoltage; { данные в вольтах } function exSEM_Code:byte; { код прибора ??? что это такое?} procedure exSetCountSEM(x:word); procedure exDetectCtrl(var x:tCtrlAlive); virtual; private prBusPtr:c_Bus.tCtrlPtr; prData:tData; prTmpData:tTmpData; procedure exBlocksIn(var x:tBlocks); procedure exBlocksOut(x:tBlocks); procedure exValvesSet(x:tValves); procedure exValvesGet(var x:tValves); procedure exDone; virtual; { Чтение текущих значений ВЭУ счетчиков } procedure exSEM_Out(x:word); { код прибора и данные без преобразований ??? возможно это не так ??? (двоично-десятичное представление по тетрадам - одна десятичная цифра в 4-х битах) } function exSEM_In:word; { код прибора и данные без преобразований } procedure exSEM_DataOut(x:tSEMData); { вывод данных в двоичном представлении } function exSEM_DataIn:tSEMData; { данные в двоичном представлении } {Процедуры сохранения значений в портах} procedure exReadPortsData(var PD:tPortsArray); procedure exSavePortsData; procedure ClearPortsData; function exIsNotChangedPortsData:boolean; procedure FlagStateSet(AFlag:tFlag; AState:boolean); { Вспомогательные функции определния наличия питания, см. exIsPowerON} function PortsNumber:word; virtual; function exReadSafePorts(var PortsValues:tPortValuesArray; Count:word):boolean; virtual; end; IMPLEMENTATION USES xStrings, DataSave, MiscFunc; const cCtrlAlive=4; { число портов <>$FF для "живого" контроллера, используется для детектирования наличия } {биты, задействованные в порту контороля вкл./выкл. блоков} cBlocksMask=[fBPGI, f10kV, fSEM, fValvesControl]; {ВСЕ блоки} cAllBlocks=[fBPGI, f10kV, fSEM, fValvesControl]; cDefaultPorts:tPorts=( rwSEMDACLowByte :$33; rwSEMDACUpByte_SEMCode:$32; rwBlocks :$31; rwValves :$30 ); { Маска переключателей ВХОД/ВЫХОД } cvfInOutMask=[fLine2Out, fLine2In, fLine1Out, fLine1In]; { Маска переключателей источника } cvfSourceMask= [fS0, fS1, fS2]; { Шаблоны переключения источников } cvfCloseAll= [ ]; {0} cvfSample1= [fS0 ]; {1} cvfSample2= [ fS1 ]; {2} cvfStandard1=[fS0, fS1 ]; {3} cvfStandard2=[ fS2]; {4} cvfStandard3=[fS0, fS2]; {5} cvfStandard4=[ fS1, fS2]; {6} cvfPumping =[fS0, fS1, fS2]; {7} type { источники } tSourceSwitches=array[tSource] of tValves; const { Массив шаблонов переключения источников (для быстрой трансляции источник->маска)} cSources2Mask:tSourceSwitches=( cvfCloseAll, cvfSample1, cvfSample2, cvfStandard1, cvfStandard2, cvfStandard3, cvfStandard4, cvfPumping, cvfCloseAll ); type tSrcNum=0..7; tMasks=array[tSrcNum] of tSource; const cMask2Source:tMasks=( sCloseAll, sSample1, sSample2, sStandard1, sStandard2, sStandard3, sStandard4, sPumping ); {------------------------------------------------------------------------} { Инициализация (без ввода/вывода в порты)} constructor tCtrl.Init(var Bus:c_Bus.tCtrl; Ports:tPorts); begin Inherited Init; prBusPtr:=@Bus; prData.Ports:=Ports; prData.Flags:=[]; prData.LastSEM:=0; prData.LastBlocks:=[fBPGI]; prData.LastValves:=[]; MarkTime; prTmpData.Flags:=[]; xMarkTime(prTmpData.LastValvesSwitchTime); prData.BlocksSwitchTimeOutResolution:=5; BlocksSwitchTimeOutSet(cSwitchDelay); SEMCoeffSet(ckV2SEM_koeff); ClearPortsData; If (Bus.Error) and (NoError) then begin SetErrorCode(tErrorCode(ecBadBus)); end; end; constructor tCtrl.InitDefault(var Bus:c_Bus.tCtrl); begin Init(Bus, cDefaultPorts); end; destructor tCtrl.Done; begin if NotInitialized then Exit; Inherited Done; prBusPtr:=nil; prTmpData.Flags:=[fDone]; end; function tCtrl.Name; begin Name:='Panel'; end; function tCtrl.Restore(var DataPtr:pointer):boolean; begin if Inherited Restore(DataPtr) then Restore:=RestoreDataEx(DataPtr, prData, SizeOf(prData)) else Restore:=FALSE; end; function tCtrl.Save(var DataPtr:pointer):boolean; begin if Inherited Save(DataPtr) then Save:=StoreDataEx(DataPtr, prData, SizeOf(prData)) else Save:=FALSE; end; function tCtrl.DataSize:word; begin DataSize:=Inherited DataSize + DataSave.SizeOfData(SizeOf(prData)); end; {------------------------------------------------------------------------} { Установка параметров (без ввода/вывода в порты)} function tCtrl.Flags:tFlags; begin Flags:=prData.Flags; end; function tCtrl.FlagSet(AFlag:tFlag; AState:boolean):boolean; begin FlagSet:=AFlag in prData.Flags; if AState then Include(prData.Flags,AFlag) else Exclude(prData.Flags,AFlag); end; function tCtrl.FlagState(AFlag:tFlag):boolean; begin FlagState:=AFlag in prData.Flags; end; procedure tCtrl.FlagStateSet(AFlag:tFlag; AState:boolean); begin if AState then Exclude(prData.Flags, AFlag) else Include(prData.Flags, AFlag); end; (*function tCtrl.ValvesClosingOnExDone:boolean; begin ValvesClosingOnExDone:=not (fSkipValvesClosingOnExDone in prData.Flags); end; function tCtrl.ValvesClosingOnExInit:boolean; begin ValvesClosingOnExInit:=not (fSkipValvesClosingOnExInit in prData.Flags); end; function tCtrl.ValvesRestoreOnExInit:boolean; begin ValvesRestoreOnExInit:=(fValvesRestoreOnExInit in prData.Flags); end; procedure tCtrl.ValvesClosingOnExDoneSet; begin FlagStateSet(fSkipValvesClosingOnExDone,x); end; procedure tCtrl.ValvesClosingOnExInitSet; begin FlagStateSet(fSkipValvesClosingOnExInit,x); end; procedure tCtrl.ValvesRestoreOnExInitSet(x:boolean); begin FlagStateSet(fValvesRestoreOnExInit,x); end; *) function tCtrl.BlocksSwitchTimeOut:word; begin BlocksSwitchTimeOut:=prData.BlocksSwitchTimeOut; end; procedure tCtrl.BlocksSwitchTimeOutSet(x:word); begin prData.BlocksSwitchTimeOut:=x; end; function tCtrl.BlocksSwitchTimeOutResolution:word; begin BlocksSwitchTimeOutResolution:=prData.BlocksSwitchTimeOutResolution; end; {------------------------------------------------------------------------} { Чтение текущих значений параметров (без ввода/вывода в порты)} {------------------------------------------------------------------------} { Вспомогательные функции (без ввода/вывода в порты)} procedure tCtrl.SetNoError; begin prBusPtr^.SetNoError; Inherited SetNoError; end; function tCtrl.ErrorMessage(en:tErrorCode):string; begin case tErrorCodes(en) of ecFailBlocks: ErrorMessage:='Ошибка включения/выключения блоков'; ecFailCurBlocks: ErrorMessage:='Ошибка чтения состояния вкл./выкл. блоков'; { ecBadBlocksCombination: ErrorMessage:='Попытка включения 10кВ и ВЭУ одновременно';} ecFailValves: ErrorMessage:='Ошибка установки состояния вкл./выкл. клапанов'; ecFailCurValves: ErrorMessage:='Ошибка чтения состояния вкл./выкл. клапанов'; ecFailSource: ErrorMessage:='Ошибка открытия клапана источника'; ecFailInOut: ErrorMessage:='Ошибка открытия клапана магистрали'; ecFailValvesControlEnable: ErrorMessage:='Ошибка установки разрешения/запрета на управление клапанами'; ecFailCurValvesControlEnable: ErrorMessage:='Ошибка чтения состояния разрешения/запрета на управление клапанами'; ecFailWriteSEM: ErrorMessage:='Ошибка записи в ЦАП ВЭУ'; ecFailReadSEM: ErrorMessage:='Ошибка чтения из ЦАП ВЭУ'; ecBadControllerState: ErrorMessage:='Ошибочное состояние контроллера'; else ErrorMessage:=Inherited ErrorMessage(en)+' (панель управления)'; end; end; {------------------------------------------------------------------------} { Исполняемые функции (ввод/вывод в порты)} procedure tCtrl.exInit; var b:tBlocks; begin Inherited exInit; If IsExInitDone then begin if FlagState(fBlocksRestoreOnExInit) then begin {Восстанавливаем состояние блоков, !!!за исключением контроля клапанов } Exclude(prData.LastBlocks,fValvesControl); exBlocksONGet(b); exBlocksONSet(prData.LastBlocks+[fValvesControl]*b); end; if FlagState(fValvesRestoreOnExInit){ValvesRestoreOnExInit} then begin exBlockONSet(fValvesControl); exValvesSet(prData.LastValves); end else if not FlagState(fSkipValvesClosingOnExInit){ValvesClosingOnExInit} then begin exBlocksONGet(b); exBlockONSet(fValvesControl); exSourceSet(sCloseAll); exBlocksONSet(b); end; if FlagState(fBlocksRestoreOnExInit) then begin exSEM_ValueSet(prData.LastSEM); end; SetExInitDone(NoError); end; OperationTimeReset(0); end; procedure tCtrl.exDone; var bs:tBlocks; LastBlks:tBlocks; LastValves:tValves; begin if not CheckExInitDone then Exit; if not (tErrorCodes(ErrorCode) in [ecNotInitialized, ecBadControllerState, ecBadBus]) then begin LastBlks:=prData.LastBlocks; LastValves:=prData.LastValves; SetNoError; if FlagState(fSkipValvesClosingOnExDone){ValvesClosingOnExDone} then begin exBlockONSet(fValvesControl); exSourceSet(sCloseAll); SetNoError; exBlocksONSet([]); end else begin exBlocksONGet(bs); exBlocksONSet(bs*[fValvesControl]); end; prData.LastBlocks:=LastBlks; prData.LastValves:=LastValves; end; Inherited exDone; exSavePortsData; end; { Установка параметров } procedure tCtrl.exBlocksONSet(x:tBlocks); var z:tBlocks; TimeInterval:tTimeInterval; begin if IsExInitDone then begin If NoError then begin OperationTimeSet(BlocksSwitchTimeOut*2); exBlocksOUT(cBlocksMask*tBlocks(not Byte(x))); TimeInterval.Start(BlocksSwitchTimeOut); x:=x*cBlocksMask; exBlocksONGet(z); while (z<>x) and TimeInterval.NotIntervalEnd and NoError do begin prBusPtr^.Delay(BlocksSwitchTimeOutResolution); exBlocksONGet(z); end; if (z<>x) then begin SetErrorCode(tErrorCode(ecFailBlocks)); end; prData.LastBlocks:=z; end; OperationTimeReset(0); end else begin prData.LastBlocks:=x; end; end; procedure tCtrl.exSourceSet(x:tSource); var z:tValves; begin if exValvesControlEnable and (x<>sBad) then begin exValvesGet(z); {$IfOpt R+} if cMask2Source[Byte(cSources2Mask[x])]<>x then RunError(201); {$EndIf Opt R+} z:=(z*cvfInOutMask)+cSources2Mask[x]; exValvesSet(z); end else begin SetErrorCode(tErrorCode(ecFailSource)) end; end; procedure tCtrl.exInOutOpenSet(x:tValves); var z:tValves; begin CheckExInitDone; exValvesGet(z); z:=(z*cvfSourceMask)+(x*cvfInOutMask); exValvesSet(z); end; { Чтение текущих значений параметров } procedure tCtrl.exBlocksONGet(var x:tBlocks); begin if IsExInitDone then begin If NoError then begin exBlocksIN(x); if prBusPtr^.Error then begin SetErrorCode(tErrorCode(ecFailCurBlocks)) end; end; OperationTimeReset(0); end else begin x:=prData.LastBlocks; end; end; function tCtrl.exBlockOnSet(x:tBlock):boolean; var z:tBlocks; begin exBlocksONGet(z); Include(z,x); exBlocksOnSet(z); exBlockOnSet:=exBlockONGet(x); end; function tCtrl.exBlockOffSet(x:tBlock):boolean; var z:tBlocks; begin exBlocksONGet(z); Exclude(z,x); exBlocksOnSet(z); exBlockOffSet:=not exBlockONGet(x); end; function tCtrl.exBlockONGet(x:tBlock):boolean; var b:tBlocks; begin exBlocksONGet(b); exBlockONGet:=(x in b) and NoError; end; function tCtrl.exSource:tSource; var z:tValves; begin CheckExInitDone; exValvesGet(z); exSource:=sBad; If NoError then begin z:=z*cvfSourceMask; {$IfOpt R+} if cSources2Mask[cMask2Source[Byte(z)]]<>z then RunError(201); {$EndIf Opt R+} exSource:=cMask2Source[Byte(z)]; end; OperationTimeReset(0); end; procedure tCtrl.exInOutOpenGet(var x:tValves); var z:tValves; begin CheckExInitDone; exValvesGet(z); x:=(z*cvfInOutMask); OperationTimeReset(0); end; function tCtrl.exValvesControlEnable:boolean; begin exValvesControlEnable:=exBlockOnGet(fValvesControl); OperationTimeReset(0); end; procedure tCtrl.exSEM_ValueSet; { данные в вольтах } begin CheckExInitDone; exSEM_DataOut((x*SEMCoeff+(ckV2SEM_Scale div 2)) div ckV2SEM_Scale); OperationTimeReset(0); end; function tCtrl.exSEM_Value; { данные в вольтах } var x:longint; begin CheckExInitDone; if NoError then begin x:=SEMCoeff; prData.LastSEM:=(Longint(exSEM_DataIn)*ckV2SEM_Scale+(x div 2)) div x; end; exSEM_Value:=prData.LastSEM; end; procedure tCtrl.exSetCountSEM(x:word); begin if x>SEMCountMax then RunError(201); exSEM_ValueSet(SEMMin+x*SEMStep); OperationTimeReset(0); end; function tCtrl.SEMMax:word; begin SEMMax:=cMaxSEM_U; end; function tCtrl.SEMMin:word; begin SEMMin:=cMinSEM_U; end; function tCtrl.SEMStep:word; var x:longint; begin x:=SEMCoeff; SEMStep:=(1000+(x div 2)) div x; end; function tCtrl.SEMCountMax:word; begin SEMCountMax:=(SEMMax-SEMMin+(SEMStep div 2)) div SEMStep; end; function tCtrl.SEMCount:word; begin SEMCount:=(exSEM_Value-SEMMin+(SEMStep div 2)) div SEMStep; end; {------------------------------------------------------------------------} { * PRIVATE секция } procedure tCtrl.exBlocksIn(var x:tBlocks); begin x:=cBlocksMask*tBlocks(prBusPtr^.exInByte(prData.Ports.rwBlocks)); end; procedure tCtrl.exBlocksOut(x:tBlocks); begin {$IfDef Seg16} x:=cBlocksMask*x; prBusPtr^.exOutByte(prData.Ports.rwBlocks,Byte(x)); {$ELSE} prBusPtr^.exOutByte(prData.Ports.rwBlocks,Byte(cBlocksMask*x)); {$EndIf} end; procedure tCtrl.exValvesSet(x:tValves); var z:tValves; TimeInterval:tTimeInterval; begin If NoError then begin OperationTimeSet(BlocksSwitchTimeOut*2); { Задержка включена для обеспечения срабатывания реле, иначе были проблемы с переключением при быстрых последовательных вызовах } prBusPtr^.exOutByte(prData.Ports.rwValves,Byte(x)); TimeInterval.Start(BlocksSwitchTimeOut); exValvesGet(z); while (x<>z) and (not TimeInterval.IntervalEnd) and NoError do begin prBusPtr^.Delay(BlocksSwitchTimeOutResolution); exValvesGet(z); end; if (x=z) then begin prData.LastValves:=z; end else begin SetErrorCode(tErrorCode(ecFailValves)) end; end; end; procedure tCtrl.exValvesGet; begin If NoError then begin Byte(x):=prBusPtr^.exInByte(prData.Ports.rwValves); if prBusPtr^.Error then begin SetErrorCode(tErrorCode(ecFailCurValves)) end; end else begin Byte(x):=$FF; end; end; procedure tCtrl.exDetectCtrl(var x:tCtrlAlive); var c:word; begin c:=prBusPtr^.exScanNotFFports(prData.Ports, (SizeOf(prData.Ports) shr 1)); case c of cCtrlAlive: x:=aYes; 0: x:=aNo; else if c>=(cCtrlAlive shr 1) then x:=aMayBeYes else x:=aMayBeNo; end; end; procedure tCtrl.exSEM_Out(x:word); { данные и код прибора без преобразований } begin prBusPtr^.exOutByte(prData.Ports.rwSEMDACLowByte, tWord(x).LoByte); prBusPtr^.exOutByte(prData.Ports.rwSEMDACUpByte_SEMCode, tWord(x).HiByte); if prBusPtr^.Error then begin SetErrorCode(tErrorCode(ecFailWriteSEM)); end; end; function tCtrl.exSEM_In:word; { данные и код прибора без преобразований } var w:word; begin tWord(w).LoByte:=prBusPtr^.exInByte(prData.Ports.rwSEMDACLowByte); tWord(w).HiByte:=prBusPtr^.exInByte(prData.Ports.rwSEMDACUpByte_SEMCode); exSEM_In:=w; if prBusPtr^.Error then begin SetErrorCode(tErrorCode(ecFailReadSEM)); end; end; function tCtrl.exSEM_Code:byte; { код прибора } begin exSEM_Code:=(exSEM_In shr 12); OperationTimeReset(0); end; function tCtrl.exSEM_DataIn:tSEMData; { данные преобразованные к бинарной форме } begin exSEM_DataIn:=(exSEM_In and $0FFF); end; procedure tCtrl.exSEM_DataOut(x:tSEMData); { данные преобразованные к бинарной форме } begin exSEM_Out(($0FFF and x)+(exSEM_In and $F000)); end; procedure tCtrl.exReadPortsData; var i:tPort; begin ClearPortsDataX(PD); if (NoError) then begin for i:=Low(tPort) to High(tPort) do begin if prBusPtr^.NoError then begin if not (i in cUnreadablePorts) then PD[i]:=prBusPtr^.exInByte(prData.Ports.Ports[i]); end else begin SetErrorCode(Ord(ecFailReadPortsData)); break; end; end; end; end; procedure tCtrl.exSavePortsData; begin exReadPortsData(prData.PortsData); end; procedure tCtrl.ClearPortsData; begin ClearPortsDataX(prData.PortsData); end; function tCtrl.exIsNotChangedPortsData:boolean; var PD:tPortsArray; begin exReadPortsData(pd); exIsNotChangedPortsData:=Equal(PD,prData.PortsData,SizeOf(PD)); end; procedure tCtrl.SEMCoeffSet; begin prData.SEM_coeff:=x; end; function tCtrl.SEMCoeff; begin SEMCoeff:=prData.SEM_coeff; end; function tCtrl.PortsNumber:word; begin PortsNumber:=Succ(Ord(High(tPort))); end; function tCtrl.exReadSafePorts(var PortsValues:tPortValuesArray; Count:word):boolean; var i:tPort; begin exReadSafePorts:=FALSE; if NoError and (Count=PortsNumber) then begin for i:=Low(tPort) to High(tPort) do begin if prBusPtr^.NoError then begin if not (i in cUnreadablePorts) then PortsValues[Ord(i)]:=prBusPtr^.exInByte(prData.Ports.Ports[i]) else PortsValues[Ord(i)]:=$FF; end else begin SetErrorCode(Ord(ecFailReadPortsData)); break; end; end; if prBusPtr^.Error then SetErrorCode(Ord(ecFailReadPortsData)) else exReadSafePorts:=TRUE; end; end; END. { Контроллер пульта управления (АК3) 5.105.184 г========T================T=====================================¬ ¦ Адрес ¦ ПОРТ ¦ ¦ ¦ порта +-------T--------+ Назначение ¦ ¦ ¦чтение ¦запись ¦ ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $33 ¦ + ¦ + ¦ младший байт ЦАПа ВЭУ ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $32 ¦ + ¦ + ¦ мл. тетрада - ст. тетрада ЦАПа ВЭУ ¦ ¦ ¦ ¦ ¦ ст. тетрада - код прибора ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $31 ¦ + ¦ + ¦ Вкл./выкл. блоков ¦ ¦ ¦ ¦ ¦ (см. рис.2) ¦ ¦--------+-------+--------+-------------------------------------¦ ¦ $30 ¦ + ¦ + ¦ Запись - управление клапанами ¦ ¦ ¦ ¦ ¦ чтение - состояние клапанов ¦ ¦ ¦ ¦ ¦ (см. рис.3) ¦ L========¦=======¦========¦=====================================- ------T-----T-----T-----T-----T-----T-----T-----¬ ¦ D7 ¦ D6 ¦ D5 ¦ D4 ¦ D3 ¦ D2 ¦ D1 ¦ D0 ¦ L--T--+--T--+--T--+--T--+--T--+--T--+--T--+--T--- X X X X ¦ ВЭУ 10kV БПГИ ¦ L-----+------ ¦ 0 - блок вкл. ¦ 1 - блок выкл. -------+-----¬ управление клапанами 0 - разрешено 1 - запрещено Рис. 2 ------T-----T-----T-----T-----T-----T-----T-----¬ ¦ D7 ¦ D6 ¦ D5 ¦ D4 ¦ D3 ¦ D2 ¦ D1 ¦ D0 ¦ L--T--+--T--+--T--+--T--+--T--+--T--+--T--+--T--- VE2 VE1 VE11 VE10 X ¦ ¦ ¦ "Вх1" "Вых1""Вх2" "Вых2" ¦ ¦ ¦ L-----+--T--+------ ¦ ¦ ¦ 0-выкл. ¦ ¦ ¦ 1-вкл. ---+--T--+--T--+--¬ все откл. -- ¦ 0 ¦ 0 ¦ 0 ¦ +-----+-----+-----+ "Проба1" VE3 вкл. -- ¦ 0 ¦ 0 ¦ 1 ¦ +-----+-----+-----+ "Проба2" VE9 вкл. -- ¦ 0 ¦ 1 ¦ 0 ¦ +-----+-----+-----+ "Эталон1" VE4 вкл. -- ¦ 0 ¦ 1 ¦ 1 ¦ +-----+-----+-----+ "Эталон2" VE5 вкл. -- ¦ 1 ¦ 0 ¦ 0 ¦ +-----+-----+-----+ "Эталон3" VE7 вкл. -- ¦ 1 ¦ 0 ¦ 1 ¦ +-----+-----+-----+ "Эталон4" VE8 вкл. -- ¦ 1 ¦ 1 ¦ 0 ¦ +-----+-----+-----+ "Откачка" VE6 вкл. -- ¦ 1 ¦ 1 ¦ 1 ¦ L-----+-----+------ Рис. 3 }