Design IdeasDecember 19, 1996 |
The circuit in
Figure
1 uses a microcontroller (PIC16C71) as an A/D converter and a data
organizer. The circuit plugs directly into a PC printer port and needs no
external power supply. Under the control of the Borland C program in Listing 1,
the µC selects one of three analog channels, performs A/D conversion, sends low
and high nibbles of converted data back to the printer port, and waits for the
next command.
Although the printer port can power the µC through one of its output lines, the voltage can vary from PC to PC. To generate reliable data, an LM385 2.5V reference diode provides the reference for the A/D conversion. The three channel inputs should remain in the 0 to 2.5V range.
The Borland C program reads three channels in a round-robin fashion, reforms 8-bit data, and converts the data to three vertical bars. The program also creates a graphic window and displays the results. This listing, as well as an assembly language listing for the µC, are available for downloading from EDN's Web site: http://www.ednmag. com. At the registered-user area, go into the "Software Center" to download the file from DI-SIG, #1962. (DI #1962)
| Listing 1 --Conversion Control Program | |
|
#include <graphics.h> #include <stdlib.h> #include <stdio.h> #include <conio.h> #include <dos.h> #include <bios.h> #include <math.h> #define POWER_ON 0x01 #define HIGH_BYTE 0x10 #define CHANNEL_OFF 0x01 #define POWER_OFF 0x00 typedef unsigned int WORD; int data, out_port, in_port, out=0, channel; char msg[80]; void read_data(void) { out |= (int)(pow(2, channel)); outportb(out_port, out); /* set port to selected channel */ delay(5); out &= CHANNEL_OFF; outportb(out_port, out); /* set port to read low nibble */ delay(5); data=(inport(in_port)/8) & 0x0f; /* read low nibble */ out |= HIGH_BYTE; outportb(out_port, out); /* set port to read high nibble */ delay(5); data+=(inport(in_port)*2) & 0xf0; /* combine high and low nibbles */ out &= CHANNEL_OFF; outportb(out_port, out); /* clean output */ delay(5); } void display_data(void) { setviewport(213*(channel-1)+100, 31, 213*(channel-1)+110, 300, 1); clearviewport(); setfillstyle(1, YELLOW); bar(1, 270-data, 10, 270); setviewport(213*(channel-1)+90, 320, 213*(channel-1)+125, 340, 1); clearviewport(); sprintf(msg, "%.2f",((float)data)*2.5/256); outtext(msg); /* show data on screen */ delay(100); } void init_screen(void) /* initialize display screen */ { setbkcolor(BLUE); setcolor(WHITE); line(2,2,637,2); line(5,4,634,4); line(2,2,2,477); line(5,4,5,475); line(5,475,634,475); line(2,477,637,477); line(634,5,634,475); line(637,2,637,477); |
line(5,350,634,350); setviewport(450, 440, 630, 460, 1); sprintf(msg, "press any key to quit"); outtext(msg); setviewport(90, 20, 140, 30, 1); sprintf(msg, "CH 1"); outtext(msg); setviewport(303, 20, 353, 30, 1); sprintf(msg, "CH 2"); outtext(msg); setviewport(516, 20, 566, 30, 1); sprintf(msg, "CH 3"); outtext(msg); setviewport(0, 0, 639, 479, 1); } int init_graph(void) /* initialize graphic mode */ { int gdriver = DETECT, gmode, errorcode; initgraph(&gdriver, &gmode, ""); errorcode = graphresult(); if (errorcode != grOk) { printf("Graphics error: %s\n", grapherrormsg(errorcode)); printf("Press any key to halt:"); getch(); exit(1); } return 0; } void find_port(void) /* find printer port address */ { out_port=*(WORD far *)MK_FP(0x0040,8); in_port=out_port+1; out|=POWER_ON; outportb(out_port, out); /* power on */ delay(1000); } void clean_up(void) /* close graphic mode */ { closegraph(); out &= POWER_OFF; outportb(out_port, out); /* turn off power supply */ } void main(void) { find_port(); init_graph(); init_screen(); do { for (channel=1; channel<4; channel++) { read_data(); display_data(); } } while (!kbhit()); /* quit if hit any key */ clean_up(); } |
| EDN Access | feedback | subscribe to EDN! |