The A/D converter connected to the parallel port
Schematic from: AD976 - 16-Bit, 100 kSPS, Parallel I/O A/D Converter
with connections to the parallel port.
If you're using an extension cable for the port (i.e. 3 meters), you'll need a driver/buffer for
the ADC. The ADC alone is not able to drive the long cable. I added a 74HC244 and it works pretty well!
Here's a small chunk of C-code for reading the ADC (AD976).
Connections between the ADC and the parallel port:
| AD976 | parallel port (D-Type 25) |
| BYTE pin 23 | AUTOFEED pin 14 |
| R/C pin 24 | STROBE pin 1 |
| BUSY pin 26 | ACK pin 10 |
| DB0-7 pin 22-15 | D0-7 pin 2-9 |
| GND pin 18-25 |
This program for LINUX will read the ADC until a key on the keyboard is pressed and prints the values:
ie. high: 47 low: 164 res=12196
C source code
Access the parallel port on Sun Solaris OS
#include <stdio.h>
#include <stdlib.h>
#include <asm/io.h>
#include <termios.h>
#define BASEPORT 0x378
// INTERFACING AN ADC976 16bit AD converter
// (see www.analog.com for datasheet)
// (C) 2003 http://www.magnetometer.org
// feel free to use and/or modify this code anywhere, anytime,
// as long as this header remains unchanged.
// BE CAREFUL WHEN PLAYING AROUND WITH YOUR PARALLEL PORT
// BETTER USE AN EXTRA I/O CARD! Replacing a single card
// is much cheaper than a new motherboard!
// PARALLEL PORT PINS USED:
// STROBE: pin 1 ; bit 0 CONTROL REGISTER BASEPORT+2
// AUTOFEED: pin 14 ; bit 1 CONTROL REGISTER BASEPORT+2
// (ACK: pin 10 ; bit 6 STATUS REGISTER BASEPORT+1; not used here)
// PORT: pin 2-9; bit 0-7 DATA REGISTER BASEPORT
// STROBE & AUTOFEED is hardware inverted
//
// CONTROL REGISTER:
// I/O: bit 5 in BASEPORT+2 set to HIGH means the port is in input mode
// compile on linux with i.e. gcc -O2 -o adc adc.c
// this example reads the ADC until a key on the keyboard is pressed
int main(int argc, char **argv) {
if (ioperm(BASEPORT, 3, 1)) {
// ask for permissions to access the parallel port
// YOU MUST BE ROOT TO ASK FOR THIS SORT OF PERMISSION, so
// don't forget to 'su' yourself ;-)
// we don't want to interfere with other code
// usage of ioperm: BASEPORT ... base address we want to use
// 3 ... the next 3 bytes
// 1 ... we want the permission
perror("ioperm open");
exit(1);
}
makeinput(); // set the port to input mode
int res = 0;
int i = 0;
while (1) {
// start conversion
// sets STROBE to HIGH, pin 1 = LOW
outb(33,BASEPORT+2);
usleep(2000); // wait for conversion
// switch to read-mode
// sets STROBE to LOW, pin1 to HIGH; STROBE = pin 1, bit0 in BASEPORT+2
outb(32, BASEPORT + 2);
usleep(2000); // wait
int high = inb(BASEPORT); //read low byte
// switch to high byte -> AUTOFEED = pin 14, bit 1 in BASEPORT+2
outb(34, BASEPORT + 2);
usleep(2000); // wait for high byte
int low = inb(BASEPORT); // read high byte
res = high*256 + low; // calculate the 16 bit value
printf("high: %d low: %d res=%d\n", high, low,res);
if (kbhit()) {
break;
}
}
freeperm(); // tell the system we do not use the port anymore
exit(0);
}
int freeperm() {
if (ioperm(BASEPORT, 3, 0)) {
// tell the system we do not use the port anymore
// usage of ioperm: BASEPORT ... base address we want to use
// 3 ... the next 3 bytes
// 0 ... free the permission
perror("ioperm close");
}
}
int makeinput() { // sets the port to input mode & checks if it was successful
outb(33, BASEPORT + 2); // set to input mode and make STROBE high
// we double check if the port is really on input mode
// some older systems might not support bidirectional mode
// at least this is what I have read in some docs
outb(147, BASEPORT);
if (inb(BASEPORT) == 147) {
printf("your system doesn't support bi-directional mode: err%d\n", 147);
exit(1);
}
outb(201, BASEPORT);
if (inb(BASEPORT) == 201) {
printf("your system doesn't support bi-directional mode: err%d\n", 201);
exit(1);
}
return 1;
}
int kbhit(void) { // check if a key on the keyboard is pressed
struct termios term, oterm;
int fd = 0;
int c = 0;
tcgetattr(fd, &oterm);
memcpy(&term, &oterm, sizeof(term));
term.c_lflag = term.c_lflag & (!ICANON);
term.c_cc[VMIN] = 0;
term.c_cc[VTIME] = 1;
tcsetattr(fd, TCSANOW, &term);
c=getchar();
tcsetattr(fd, TCSANOW, &oterm);
if (c != -1) ungetc(c, stdin);
return ((c!=-1)?1:0);
}
Last-Modified: Mon, 07 May 2007 18:00:30 GMT
|