This article describes a simple way to interface the ADC0804 8-bit analog-to-digital converter IC to the parallel port of an IBM-compatible PC. It largely superceeds my old page on how to interface the (now obsolete) ZN448E.

The ADC0804 from National Semiconductor is a simple, cheap, easily-available 8-bit ADC. By default, the analog input range is 0 to 5V, but by using an external reference, and/or lifting the Vin- pin above GND, a wide range of input levels can be catered for. With a maximum sampling rate of 8kHz, low-quality audio work could be attempted.

See the manufacturers information and datasheet on the ADC0804 at www.national.com/pf/AD/ADC0804.html, and also my Introduction to parallel port interfacing.

Simplest ADC interface circuit

NB. Requires at least "BIDIRECTIONAL" parallel port

The IC draws only 1mA power, so the 5V supply can be taken from a 78L05 regulator and a PP3 battery or wall plug-in PSU. In fact, the IC still seems to work with no external power, owing to currents flowing down the signal lines from the PC (however this is not recommended, especially for accurate measurements)!


                       +5v --@--         ---                 parallel
                             |          |   |                 port
                             |          |   v GND             
                             |          |                    'D'          reg.
			--------------------------           pin  name    bit
		       |     20         1         |
		       |    Vcc        -CS        |
		       |                   -intr 5|--->----- 15  -Error   S3+
		       |                          |
		       |                    -RD  2|---<-----  1  -Strobe  C0-
      analog           |                    -WR  3|---<----- 16  -Init    C2+
      signal  ----->---|6 Vin+                    |    MSB
      0 - 5v           |                     D7 11|--->-----  9  D7       D7
		       |                     D6 12|--->-----  8  D6       D6
		   ----|7 Vin-               D5 13|--->-----  7  D5       D5
		  |    |                     D4 14|--->-----  6  D4       D4
		  |    |                     D3 15|--->-----  5  D3       D3
		  v    |        ADC0804      D2 16|--->-----  4  D2       D2
		 GND   |                     D1 17|--->-----  3  D1       D1
		       |                     D0 18|--->-----  2  D0       D0
		       |                          |    LSB
		NC ----|9 Vref/2                  |
		       |                          |
		       |   Clk   Clk    An   Dig  |
		       |    R    in     GND  GND  |      --- 18  GND      N/A
		       |   19     4      8    10  |     |    -25
			--------------------------      |
                            |     |      |    |         |
                        10k| |    |      |    |         v
			   | |    |      |    |        GND
			    |	  |      v    v
			     -----@     GND  GND
				  |
				  |
			    150pF---
				 ---
				  |
				  v
				 GND

...and the program you need (C++ version)
// Program to collect data from a parallel port ADC,
// 8-bits at a time using simple bi-dir protocol.

// Reading data from ADC0804LCN
// (NB Circuit will self-power off port!!!)


// (C) W.A. Steer 1998


#include <iostream.h>
#include <dos.h>

// Some (symbolic) constants...
const c0=1, c1=2, c2=4, c3=8;
const s0=1, s1=2, s2=4, s3=8;

void main()
{
 // Set the port address variables etc.
 unsigned base, data, stat, ctrl, eppdata;

 base=0x278;  // 0x278 for LPT2
              // 0x378 for LPT1

 data=base; stat=base+1; ctrl=base+2; eppdata=base+4;

 unsigned char value;
 int lc;


 for (int sample=0; sample<3000; sample++)
 {
  // To read a value from the ADC...

  // Initialise ADC conversion (pulse C2+, 'D' pin 16, LOW momentarily)
  outportb(ctrl, 32);
  outportb(ctrl, 36);

  // wait until conversion complete (until S3+, 'D' pin 15, goes HIGH)
  lc=0; do { lc++; } while (((inportb(stat) & s3)==0) && (lc!=256));

  if (lc==256) cout << "Timed out. (Hardware not connected/powered/functioning?)" << endl ;
  else
  {
   outportb(ctrl, 37);  // set C0- (set 'D' pin 1 LOW), enabling ADC output
   value=inportb(data);
   outportb(ctrl, 36);  // unset C0- (set 'D' pin 1 HIGH), disabling ADC output

   cout << "ADC value: " << (unsigned int)value << endl;
  }

  // end of ADC-read procedure
 }

}
Notes on the software
The crude "wait until conversion complete" loop may need its end-count (256) increasing on fast computers. Ideally it would actually reference real time passing - no response after 100ms or so clearly indicates a failure somewhere!
Last modified: 17th October 1998
Source: http://www.ucl.ac.uk/~ucapwas/ppadc.html

© William Andrew Steer
email: [email protected]
Hosted by www.Geocities.ws

1