home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
vol_300
/
342_01
/
diofnc11.txt
< prev
next >
Wrap
Text File
|
1991-02-25
|
6KB
|
137 lines
* ----------------------------------------------------------------------
* File : DIOFNC11.TXT
* Creator : Blake Miller
* Version : 01.01.00 February 1991
* Purpose : Describe DIOFNC11.C Functions
* Revision : February 28, 1991
* -----------------------------------------------------------------------
WARNING:
--------
I do not have a multi-port board on which to test these functions.
The single-port functions work correctly, and I wrote these multi-port
functions as an extension to those single-port functions for those of you
with multi-port boards. These functions here 'seem' correct, but are
not truly debugged. You might say they are written on 'good faith'.
(In other words, they compiled, so they must work, right? Ha Ha Ha...
I love that line!)
OVERVIEW:
---------
Many Digital I/O boards have more than one Intel 8255 on them. The
other functions in the library are used for working with one digital I/O
port at a time. If several digital ports are in use in your system, then
it may be more convenient to use the Port Array (_pa_) functions. These
functions support a virtually unlimited number of digital I/O ports (limited
by the system's amount of free memory or available 80X86 hardware addresses,
whichever you run out of first...).
I generall only need to toggle individual bits at a time. The functions
supplied support the digital output port array in this manner. If necessary,
you can obtain the address of any individual element in the array and
then implement the individual port manipulation functions (which generally
require the address of the DIODAT data as one of the arguments).
IMPLEMENTATION:
---------------
Since I advocate using defines for bits and using bit associated
digital I/O instead of obscure references such as:
data = inp( 0x300 ); /* read in data */
outp ( 0x300, data | 0x0010 ); /* toggle bit 4 on */
Huh????????
Instead, you can create legible (maintainable!) code:
#define MOTOR_BIT 32
#define MOTOR_ON 1
#define MOTOR_OFF 0
dio_pa_bitput (MOTOR_BIT, MOTOR_ON); /* turn motor on! */
Seems a little easier to read, and not a whole lot less efficient.
As I had said, many boards have more than one 8255 (Notice the motor was
located at bit 32...). In order to accomodate this system for multiple
ports, there is memory for an array of DIODAT data allocated by the
dio_pa_aloc(count) function. You pass how many 8255s are in the system
(or on multiple boards for that matter, the functions do not know the
difference....), and the 8255 base addresses do not have to be located at
consecutive 80X86 hardware port addresses. This sets up the data array.
The next important step is to remember to call dio_pa_free() before
exiting the program so that the memory is returned to the operating system.
I have conveniently made dio_pa_aloc() a void function returning a void type
so that it can be installed to be called at exit with the atexit() function.
It does no harm to call dio_pa_aloc() before memory has been allocated with
dio_pa_aloc(void) function. Those two functions, then, reserve and free the
memory for the DIODAT data buffers.
Next, the address of each 8255 must be set. Use the function
dio_pa_setadr (element, address) and call it once for each 8255 in
the system. The base address of each 8255 must be used. On most boards,
each 8255 on the board is 4 addresses away from the previous one. So, for
example, if your board has four 8255s (Computer Boards, Inc. CIO-DIO96
is one such board) and the board's base address is set to 0x300, then the
first 8255 address (Element 0) is set up with this call:
#define DIO96_BASE 0x300
dio_pa_setadr (0, DIO86_BASE);
Since there are four 8255 on the board, you can even set up a loop:
for (i = 0; i < 4; i++ ){
dio_pa_setadr (i, DIO96_BASE + (i * 4) );
}
So far, we have memory and the base addresses set up. Next step is to
program the I/O direction of the ports on the individual 8255. The default
direction is input (According to Intel documentation - RESET. A "high" on
this input clears the control register and all ports (A, B, C) are set to
the input mode."). It is a good idea to set up all your ports and then
do the approriate bit reads or writes to get the data set up correctly.
That is, to get all the data and ports into a 'known' state.
To set up all the ports as output, you can use a loop like this:
for (i = 0; i < num_port; i++ ){
dio_pa_config (i, 0, 0, 0, 0);
}
With the 8255 addresses set, and the port I/O directiosn established,
you can now proceed to use the bit functions to individually set or clear
bits in the system. Note that the total number of bits available (Base 1)
is num_bits = 24 * num_port. A loop to read all bits and print out the
state of each one as SET or CLEAR, can be written like this:
short num_bits = 24 * num_port;
short bit_state = 0;
for (bit = 0; bit < num_bits; bit++ ){
dio_pa_bitget (bit, &bit_state);
if ( bit_state ) printf ("SET \n");
else printf ("CLEAR\n");
}
A loop to sett all bits can be written like this:
for (bit = 0; bit < num_bits; bit++ ){
dio_pa_bitput (bit, 1);
}
SUMMARY:
--------
For a more detailed explanation of what each function does,
look at the source code! I have written an UNTESTED program called
DIOTST02.C which gives a general idea of how I thought the functions
coudl be used. It does not do anything useful, but demonstrates the
order in which things should be set up.
* ----------------------------------------------------------------------
* END DIOFNC11.TXT Text Description File
* ----------------------------------------------------------------------