Program Main; {M. Shill 5/16/98} Uses MuxADC; Var Average,Channel,Gain :Integer; Voltage :Real; Begin Writeln('Enter Channel (1 - 8)'); Readln(Channel); Writeln('Enter Gain (1 - 4) Gain=1 (1) Gain=2 (2) Gain=4 (3) Gain=8 (4)'); Readln(Gain); SetInput(Channel,Gain); Writeln('Enter Number of Averages'); Readln(Average); Writeln; Write('Voltage Measured is ',DVM(Average):9:6); If OVR Then Writeln(' Overrange!'); Writeln; End. Unit MuxADC; {M. Shill 5/16/98} Interface Var OVR :Boolean; Function DVM(Average: Integer):Real; Procedure SetInput(Channel,R: Integer); Procedure Calibrate; Implementation Var Addr,Range :Integer; Vlsb,Offset :Array[1..4] of Real; CalMode :Boolean; {++++ Port Input Routine ++++++++++++++++++++++++++++++++++++++++++++++++++++} Function InPort(PortAddr:Word):Byte; Var Value:Byte; Begin asm push dx mov dx, PortAddr in al,dx mov Value,al pop dx end; InPort:=Value AND $00FF; End; {++++ Port Output Routine +++++++++++++++++++++++++++++++++++++++++++++++++++} Procedure OutPort(PortAddr:Word;Value:Byte); Begin asm push dx mov dx, PortAddr mov al,Value out dx,al pop dx end; End; {++++ Parallel Port Nibble Input Routine ++++++++++++++++++++++++++++++++++++} Function ReadPort:Byte; Begin ReadPort:=((InPort(Addr+1) XOR $80) SHR 4) AND $0F; End; {++++ ADC Conversion Routine ++++++++++++++++++++++++++++++++++++++++++++++++} Function ReadADC(Average: Integer):Real; Var I : Integer; Code : Word; Sum : Real; Begin Sum:=0; For I:=1 To Average Do Begin OutPort(Addr+2,($09 XOR $0B)); {Start ADC Conversion & select -BUSY} Repeat Until (ReadPort=1); {-BUSY=1, ADC Conversion finished} OutPort(Addr+2,($00 XOR $0B)); {Select ADC High Byte, High Nibble} Code:=(ReadPort XOR $08) SHL 12; OutPort(Addr+2,($02 XOR $0B)); {Select ADC High Byte, Low Nibble} Code:=Code + ReadPort SHL 8; OutPort(Addr+2,($04 XOR $0B)); {Select ADC Low Byte, High Nibble} Code:=Code + ReadPort SHL 4; OutPort(Addr+2,($06 XOR $0B)); {Select ADC Low Byte, Low Nibble} Code:=Code + ReadPort; Sum:=Sum+Code; OutPort(Addr+2,($00 XOR $0B)); End; ReadADC:=Sum/Average; End; {++++ DVM Measurement Routine +++++++++++++++++++++++++++++++++++++++++++++++} Function DVM(Average: Integer):Real; Var Code :Real; Begin OVR:=False; Code:=ReadADC(Average); DVM:=((Code-32768)*Vlsb[Range])-Offset[Range]; If (Code>=65534) OR (Code<=1) Then OVR:=True; {DVM Overrange condition} End; {++++ Channel Select and Range Setting Routine ++++++++++++++++++++++++++++++} Procedure SetInput(Channel,R :Integer); Var Cal: Integer; Begin Cal:=0; Range:=R; If CalMode Then Cal:=1; OutPort(Addr,(Cal*32 + (Range-1)*8 + Channel-1)); End; {++++ DVM Calibration Routine++++++++++++++++++++++++++++++++++++++++++++++++} Procedure Calibrate; Var CodePFS,CodeBPZ,Ref :Real; Average,Channel,R :Integer; Begin CalMode:=True; Ref:=5; Average:=128; For R:=1 To 4 Do Begin Channel:=3; {Select 5V Reference} If R>2 Then Channel:=2; {Select 1.25V Reference if Gain=4,8} SetInput(Channel,R); {Select Calibration Mux} CodePFS:=ReadADC(Average); {Get Plus Full Scale Code} Channel:=4; {Select GND Reference} SetInput(Channel,R); CodeBPZ:=ReadADC(Average); {Get Bipolar Zero Code} If R>2 Then Ref:=1.25; Vlsb[R]:=Ref/(CodePFS-CodeBPZ); Offset[R]:=(CodeBPZ-32768)*Vlsb[R]; End; CalMode:=False; End; {++++ DVM Initialization Routine ++++++++++++++++++++++++++++++++++++++++++++} Procedure Initialize; Var p :^Word; Begin p:=ptr($40,$08); {Find Parallel Port Address from BIOS} Addr:=p^; OutPort(Addr+2,($00 XOR $0B)); {Preset ADC R/C Signal} Calibrate; {Initialize calibration first time} End; {++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++} Begin Initialize; End.