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.
|
|||
|
|
|||
|
|