RETURN to the CHEM 498C Home Page

Analog-to-Digital Conversion

The ComputerBoards CIO-AD08 is a commercial 8-channel, 12-bit, 25 u sec analog-to-digital converter for the ISA (Industry Standard Architecture) bus, the most common bus for IBM-PCs and compatibles. In this experiment you will learn how to use the CIO-AD08 to measure voltages and acquire data at timed intervals.

Equipment required: IBM-PC with XT or ISA bus, CIO-AD08 ADC card, variable DC voltage source, voltmeter.

1. Installation. Read pages 3 through 7 of the CIO-AD08 manual, which explains the installation and operation of the board. The "base address" of an ISA board is determined by on-board switches; it makes no difference which slot the card is installed into (in contrast to the Apple boards). Make sure the base address switches are set as shown on page 3 of the CIO-AD08 manual; this makes the base address 768 decimal (300 hexadecimal). Check that the gain switches (on the back edge of the board) are set to the 0-10 volt range as described on the bottom of page 6. Plug the board into any available slot as described on page 4.

2. Programming the ADC board in in BASIC. The simplest way to read the ADC from BASIC is to access its memory locations by means of the INP function and the OUT command. For this purpose we need to access three adjacent addresses: the base address and the next two addresses (base address + 1 and base address + 2).

REM This program is written for the CIO-AD08 12-bit A/D converter
baseaddress% = 768                                   :REM  base address is 768
channel% = 0                                         :REM  channel number is zero
strobe% = baseaddress% + 1                           :REM  address to start conversion
lsbaddr% = baseaddress%                              :REM  address of least sig. byte
msbaddr% = baseaddress% + 1                          :REM  address of most sig. byte
baseplus2% = baseaddress% + 2                        :REM  baseaddress + 2
OUT baseplus2%, channel%                             :REM  Sets channel number
OUT strobe%, 0                                       :REM  Starts A/D conversion
seeifdone:IF INP(baseplus2%) >127 THEN GOTO seeifdone :REM check if ADC is done
RawData% = INP(msbaddr%) * 16 + INP(lsbaddr%) / 16    :REM read ADC value
PRINT RawData%

In this program the first 6 lines simply define some variables for convenience.

The channel number (0-7) is set by OUTputting the channel number to baseaddress% + 2.

The line OUT strobe%, 0 tells the ADC to begin conversion.

The line seeifdone:IF INP(baseplus2%) >127 THEN GOTO seeifdone checks the "End of Conversion" (EOC) bit at baseaddress% + 2, keeps checking it while it's 1, then goes on to the next line when it's 0. The EOC bit is the highest (7th) bit of baseaddress% + 2; it's 1 while the ADC is busy converting and 0 when the conversion is complete. The 7th bit has place value 128, so baseaddress% + 2 is >127 when the ADC is busy converting and <127 when conversion is complete.

The line RawData% = INP(msbaddr%) * 16 + INP(lsbaddr%) / 16 reads the two 8-bit halves of the ADC reading, combines them into one 16-bit integer, and assigns it to the variable RawData%. The last line prints the result.

Modify this program so that it loops back to take repeated readings in an infinite loop. Note that you must strobe the ADC for each separate reading; however you don't have to reset the channel number each time. Therefore you should loop back only to the 7th line. Hold down the control key and press the Break key to stop the program.

2. Modify this program so that it loops back to take repeated readings in an infinite loop. Note that you must strobe the ADC for each separate reading; however you don't have to reset the channel number each time. Therefore you should loop back only to the 8th line (OUT strobe%, 0). Hold down the control key and press the break key to stop the program.

Because the ADC has 12 bit resolution, the value of RawData% varies from 0 to 212-1, i.e. from 0 to 4095. The gain switches are set to the 0-10 volt range. Therefore an input of zero volts should give a reading of 0 and an input of 10 volts should give a reading of about 4095. Why do the readings vary slightly from reading to reading? What happens to the ADC reading when the input voltage exceeds 10 volts? What happens when the input voltage is negative? (Press the ▒ button on the Voltage Reference Source to make the output negative.)

3. a. Modify this program so that it converts RawData% into the actual voltage. Connect the output of a Heath Voltage Reference Source to the channel 0 input on the ADC as shown on page 11 of the CIO-AD08 manual. Use the program above to monitor channel.

b. Modify this program so that it computes the average of 100 ADC readings, then converts the average to voltage and prints it out. Can you think of a practical advantage to recording the average or repeat ADC readings rather than the a single ADC reading?

c) Modify this program so that it measures the voltage on each of the 8 input channels (0 through 7) and prints out a table of channel numbers and voltages.

5. In some cases it is desirable to sample the input signal as fast as possible. In such cases it will help if we simply acquire and store a certain number of data points in an array, without printing. This is what the following program does, using the integer array RawData%() to store the ADC readings. In order to determine how fast data can be taken, this program also uses the TIMER function to measure the total time elapsed and then computes the data rate, in readings per second. The variable Points% sets the number of readings to acquire.

REM This program is written for the CIO-AD08 12-bit A/D converter
DIM RawData%(10000)
Points% = 3000
baseaddress% = 768
strobe% = baseaddress% + 1
lsbaddr% = baseaddress%
msbaddr% = baseaddress% + 1
baseplus2% = baseaddress% + 2 
OUT baseplus2%, 0
starttime = TIMER
FOR count% = 1 TO Points%
   OUT strobe%, 0
   seeifdone:IF INP(baseplus2%) >127 THEN GOTO seeifdone 
   RawData%(count%) = INP(msbaddr%) * 16 + INP(lsbaddr%) / 16
NEXT count%
endtime = TIMER
PRINT Points%; "readings in"; endtime - starttime; "seconds."
PRINT "Data rate ="; Points% / (endtime - starttime); "readings/sec"

a) What data rate can you achieve? Does the data rate depend on the voltage (i.e. ADC reading)? On Points%? How does the time per sample compare to the rated 25 Ásec hardware conversion time of the CIO-AD08 ADC? What would happen if the data acquisition loop runs so fast that the ADC does not have the 25 Ásec it needs to complete its conversion before the data are read by the INP statements?

b) Note that this program stores only the raw ADC readings, not the computed voltages. It assumes that voltages would be computed after all the data are acquired. What happens to the data rate if the voltages were computed and stored point-by-point in a real array during the data acquisition?

c) Modify the program so that, after all the ADC readings are measured and stored in RawData%(), the elapsed time for each data point is computed and stored in a real array time(), assuming that the data points are equally spaced in time, i.e. that the data rate is constant during the data acquisition.

d) Acquiring 12 bit data requires two INPs and some math. Acquiring 8 bit data (resolution of 1 part in 256) would require only one INP and no math and would be expected to be faster. If speed is more important than resolution in a particular experiment, you can limit the data acquisition to 8 bits. Change the line that defines strobe% to strobe% = baseaddress% and change the data acquisition line to rawdata%(count%) = INP(msbaddr%). Run the program and compare the data rate to that of 12-bit acquisition.

e) The QuickBASIC system contains a built-in compiler that can convert your program into a stand-alone ".EXE" file, that is, an executable binary that will run independently of the QuickBASIC system. Compiling the program gives you much more room in RAM for storing large data arrays, because the memory taken up by the QuickBASIC system is freed up. Compiling can also make the program run faster (for one reason because the compiled version does not constantly read the keyboard looking for a control-break to stop the program). The only disadvantages of compiling the program is that it takes more space on the disk (the ".EXE" file is larger than the corresponding ".BAS" file) and that it is less interactive and more cumbersome that running it within the QuickBASIC environment.

To compile a program, load the program into the QuickBASIC editor in the usual way, select ALT-R, X, press TAB and then down arrow to select "stand-alone EXE file", then press M. The process takes about 30 seconds. Quit to DOS (ALT-F, X) and type the name of the program without the .BAS extension.

Compile the 12-bit and 8-bit data acquisition programs above and compare their data rates to the same programs running within the QuickBASIC environment.

6. Lab report: Make up a table listing the data rates (samples/second) of all the program modifications tried in this experiment. There is no need to submit printed program listings.

This page is maintained by Tom O'Haver , Department of Chemistry and Biochemistry, The University of Maryland at College Park. Comments, suggestions and questions should be directed to Prof. O'Haver at