206 lines
5.9 KiB
Plaintext
206 lines
5.9 KiB
Plaintext
From: fdeck@happy.helios.nd.edu (francis deck)
|
||
Subject: Cheap 12-bit ADC circuit for PC
|
||
|
||
CHEAP 12-BIT ADC FOR IBM PC
|
||
|
||
Francis J. Deck
|
||
fdeck@grumpy.helios.nd.edu
|
||
|
||
This is an 8-channel 12-bit analog-to-digital converter that hooks
|
||
up to the parallel printer port of a PC and costs well under $50.
|
||
All parts (and data sheets for the chips) are available from
|
||
Digi-Key, 1-800-DIGI-KEY. Recommended construction technique is
|
||
hand-wiring on perfboard w/ ground plane. The big decoupling
|
||
caps are mandatory, otherwise you get a lot of noise in the
|
||
readings. The resistors on the inputs limit current through the
|
||
input protection diodes of the LTC1290, which protects from
|
||
overloads of up to +/- 15 V.
|
||
|
||
Of course, this circuit is not guaranteed for accuracy, safety,
|
||
or reliability, and does not protect your computer against damage
|
||
from electric discharge or overloads. It is up to you to evaluate
|
||
the circuit for its suitability for a particular application.
|
||
|
||
Software is in Turbo Pascal, and was compiled under Version 5.0.
|
||
You may have to modify the NLPT and DELAY constants in the program
|
||
for your machine. There is a mandatory 13 microsecond delay which
|
||
is created by a software loop.
|
||
|
||
SCHEMATIC DIAGRAM
|
||
|
||
8 ----- 14
|
||
ANALOG INPUTS -----|4 MHz|---P
|
||
(+/- 2.5 V) LTC1290 | |Clock|7
|
||
1 ---------- 20 | |Osc |---G
|
||
A0 o------R------|CH0 VCC|----P | -----
|
||
2| |19 | IBM PC Parallel
|
||
A1 o------R------|CH1 ACLK|---------- Printer Port
|
||
3| |18 2 (use male DB25)
|
||
A2 o------R------|CH2 SCLK|---------------o D0
|
||
4| |17 3
|
||
A3 o------R------|CH3 DIN|---------------o D1
|
||
5| |16 10
|
||
A4 o------R------|CH4 DOUT|---------------o ACK
|
||
6| |15 4
|
||
A5 o------R------|CH5 CS'|---------------o D2
|
||
7| |14 18
|
||
A6 o------R------|CH6 REF+|------ G---o GND
|
||
8| |13 |
|
||
A7 o------R------|CH7 REF-|---G |
|
||
9| |12 |---R---P
|
||
G---|COM V-|---N |+
|
||
10| |11 Z
|
||
G---|DGND AGND|---G |
|
||
---------- G
|
||
|
||
POWER SUPPLY
|
||
|
||
+---------+-----------------o +5 V
|
||
| |
|
||
| gnd|
|
||
|+ ----- out
|
||
B |79L05|-----G
|
||
| -----
|
||
| |in
|
||
| |
|
||
+---------+-----------------o -4 V
|
||
|
||
LEGEND:
|
||
|
||
P = +5 V supply
|
||
N = negative supply
|
||
G = ground
|
||
R = 1k resistor
|
||
Z = LM336Z-2.5 precision Zener
|
||
B = 9 V battery
|
||
|
||
DECOUPLING
|
||
|
||
+5 Supply: 22 uF tantalum (watch polarity)
|
||
-4 Supply: 0.1 uF disc
|
||
REF+: 4.7 uF tantalum (watch polarity)}
|
||
|
||
{======== CONTROL ROUTINES FOR 12-BIT ADC CIRCUIT ========}
|
||
|
||
unit ltc1290;
|
||
|
||
interface
|
||
|
||
{-------- User-definable constants --------}
|
||
|
||
const
|
||
lpt1 = 1; {these define the 3 printer ports}
|
||
lpt2 = 2;
|
||
lpt3 = 3;
|
||
|
||
adc_nlpt = lpt1; {which port?}
|
||
vref = 2.48; {reference voltage}
|
||
|
||
{-------- Read an ADC channel, result in V --------}
|
||
|
||
function adc_read (ch: integer): real;
|
||
|
||
{======== Implementation Section ========}
|
||
|
||
implementation
|
||
|
||
const
|
||
sclk = 1; {SCLK line on output port}
|
||
din = 2; {DIN line on output port}
|
||
dout = 64; {DOUT line on output port}
|
||
cs = 4; {CS' line on input port}
|
||
|
||
var
|
||
lpt_addrlist: array[1..3] of word absolute $40:08; {BIOS RAM}
|
||
aout, ain: word; {input, output port addresses}
|
||
|
||
{-------- Read an ADC channel --------}
|
||
|
||
function adc_read;
|
||
|
||
const
|
||
wconst = 1 + 32 + 64; {setup for single-ended, bipolar,
|
||
MSB first}
|
||
|
||
chconst: array[0..7] of byte = (0,2,8,10,4,6,12,14); {channels}
|
||
|
||
delay = 10; {may have to be larger for '386 machines}
|
||
|
||
var
|
||
i: integer; {loop counter}
|
||
win: word; {word transmitted to ADC chip}
|
||
result: word; {word received from ADC chip}
|
||
|
||
begin
|
||
for i := 1 to delay do begin end; {software delay}
|
||
|
||
win := wconst + chconst[ch];
|
||
|
||
{transmit setup word}
|
||
|
||
port[aout] := 0; {drop CS'}
|
||
|
||
for i := 1 to 12 do begin
|
||
port[aout] := (win and 1)*din; {put bit on output}
|
||
port[aout] := (win and 1)*din + sclk; {clock it out}
|
||
win := win div 2; {shift setup word}
|
||
port[aout] := 0; {drop clock line}
|
||
end;
|
||
|
||
port[aout] := cs; {raise CS'}
|
||
|
||
for i := 1 to delay do begin end; {software delay}
|
||
|
||
{receive conversion result word}
|
||
|
||
port[aout] := 0; {drop CS'}
|
||
|
||
result := 0;
|
||
|
||
win := wconst + chconst[ch]; {retransmit setup word}
|
||
|
||
for i := 1 to 12 do begin
|
||
port[aout] := (win and 1)*din; {put bit on output}
|
||
port[aout] := (win and 1)*din + sclk; {clock it out}
|
||
result := result*2; {shift result word}
|
||
if port[ain] and dout <> 0 then result := result + 1;
|
||
port[aout] := 0; {drop clock line}
|
||
end;
|
||
port[aout] := cs; {raise CS'}
|
||
|
||
adc_read := vref*((result + 2048) and 4095)/2048 - vref;
|
||
end;
|
||
|
||
{-------- Initialization ----------}
|
||
|
||
var
|
||
dummy: real; {dummy analog input}
|
||
|
||
begin
|
||
aout := lpt_addrlist[adc_nlpt]; {find port addresses}
|
||
ain := aout + 1; {other address}
|
||
port [aout] := cs; {deselect ADC chip}
|
||
dummy := adc_read(0); {read ADC once}
|
||
end.
|
||
|
||
{======== DEMO PROGRAM FOR ADC =========}
|
||
|
||
program testltc;
|
||
|
||
uses
|
||
crt,
|
||
ltc1290;
|
||
|
||
var
|
||
i: integer;
|
||
|
||
begin
|
||
writeln ('Press a key to finish.');
|
||
while not keypressed do begin
|
||
for i := 0 to 7 do write (adc_read(i):4:4,' ');
|
||
writeln ('V');
|
||
delay (1000);
|
||
end;
|
||
end.
|
||
|
||
|