Professional Documents
Culture Documents
If you need help, you can ask your question in The Forum.
I must also stress that this is a major project and should not be attempted unlesss you have a good understanding of electronics. If done wrong, you run the risk of not only destroying the circuit, by also destroying an expensive computer as well. Double, no, triple check your work to make absolutely sure that is free from errors before installing it in any computer. DISCLAIMER: I am not responsible for any damages caused due to a lack of knowledge or mistakes in the circuit when building and using these projects. Now then, with that out of the way, on to the Parallel Port Interface.
Description
Substitutions
74LS367. Buffer 7437, 74HC37 Sockets, 18 Pin Socket (For Output), Board, Ribbon Cable, 25 Pin Connector
You operate the interface by sending bit patterns to the printer port. BASIC, GWBASIC or QBasic are the languages of choice since most computers already have them installed (in your DOS directory). If you wish, you can download control software from my files section. The command you use is the OUT command. The decimal address of most printer ports (assuming LPT1) is 888. Use this with the OUT like this:
OUT 888,X X
Although designed primarily to get data out of the computer, the printer port has 5 input lines (on some computers it could be less). You access these lines with the INP function. This time, however, the decimal address is 889. The syntax of the INP command is:
Y=INP(X)
is the variable used to store the decimal value that is returned. X is the port number, which in this case is 889.
Y
You may also use the OUT command to send data to the address lines. Just use address 890 instead of 888. Remember that there are only 4 address lines.
Part U1 U2 U3 U4 U5 MISC
Description 74LS04 Inverter 74LS00 NAND Gate 74LS32 OR Gate 74LS374 Buffer 74LS30 8 Input NAND Gate 8 Bit IBM Prototyping Board, Connector (For
Substitutions 7404, 74HC04 7400, 74HC00 7432, 74HC32 74374, 74HC374 7430, 74HC30
Output/Input), Sockets, Capacitors For IC Bypass, Wire. IC Power Pins The power connections were left off the schematic for clarity. Here they are: Chip 7400 7404 7430 7432 74374 Vcc GND 14 7 14 7 14 7 14 7 20 10
CAUTION: Be sure that the signals being sent to the input card do not exceed 5 volts or fall below ground! Parts: Total Qty. 1 1 1 1 1
Part U1 U2 U3 U4 U5
Description
Substitutions
MISC 1
74LS04 Inverter 7404, 74HC04 74LS00 NAND Gate 7400, 74HC00 74LS32 OR Gate 7432, 74HC32 74LS244 Buffer 74224, 74HC224 74LS30 8 Input NAND Gate 7430, 74HC30 8 Bit IBM Prototyping Board, Connector (For Output/Input), Sockets, Capacitors For IC Bypass, Wire.
The power connections were left of the schematic for clarity. Here they are: Chip 74LS00 74LS04 74LS30 74LS32 74LS224 Vcc GND 14 7 14 7 14 7 14 7 20 10
Back To Circuits Page | Mail Me | Search I am no longer maintaining the electronics sections of this site. For an explanation, see the electronics contact page. If you need help, you can ask your question in The Forum.
If you have built any of the interfaces on my circuits page and now want to know how to actually make use of them, this page is for you. This is a simple introduction to programming the parallel port in QBasic, QuickBasic or similar language. Note that most of the concepts in this page can also be applied to GWBASIC. If you are interested in using Visual Basic to control the port, see Programming The Parallel Port In Visual Basic. What this document will not do is give you lots of details on using bidirectional ports, DMA and other advanced topics. This document assumes that you are familiar with the basic functions of BASIC itself. The parallel port is made up of three different sections. These are the data lines, control lines and status lines. There are 8 data lines, and they are the primary means of getting information out of the port. In simple projects, you will be concentrating mostly on the data lines. The control lines are another 4 outputs. They are meant to provide control signals to the printer (such as form feed or initialize). The status lines are a standard parallel port's only inputs. There are 5 of them. They were meant to allow the printer to communicate things such as error, paper out and busy to the PC. Each section is accessed by it's own address and will act independently from the rest. This is almost as if they were different ports. The addresses are as follows: Port Address (Decimal) Address (Hex) Data Lines 888 378h Control Lines 890 37Ah Status Lines 889 379h You need to know the address of the port you want to use. You will also need two other things; the command to access the port and the number you want to set it to. The command will be explained in a little while. The ports work with numbers. These can be expressed in hex, binary or decimal, but for this document all values will be expressed in decimal. It's just easier that way. Anyway, you operate the port by sending it a number that represents the binary pattern of the physical outputs on the port. For example, to set the 8 data lines to 11111111, you would send 255. To set them to 00000000 you would send 0. Note that these are all 8 bit binary numbers, and the port is also 8 outputs. Coincidence? I think not. Now that we know how to tell the port what bit patterns we want, we have to actually apply that to the BASIC language. BASIC uses two commands to talk to the computer's ports. These are OUT and INP. OUT is a statement and is used like the following:
OUT [port],[number]
We will get to INP later. As you can see, the two parameters required are the port address and the value we want to set it to. The address can be decimal or hex, as can the value. Because there are only 8 data lines, we can only send a maximum of 255 to the port (255 is decimal for binary 11111111). The examples below illustrate sending a few different bit patterns to the data lines.
'set port to OUT 888, 0 'set port to OUT 888, 1 'set port to OUT 888, 2 'set port to OUT 888, 4 'set port to OUT 888, 8
Note that when you send a bit pattern to the port everything that was there previously is cleared. This is a convenience and also a annoyance. For example, what if we want bit 2 to always stay at 1, but want to turn bit 5 on and off in sequence? Every time we set bit 5, bit 2 is turned off, and vice versa. We will discuss how to get around this when we get to the INP function. The control lines are just as easy to control, but there are a few differences. First, the address of the port is 890. Second is that there are only 4 outputs, so the highest decimal representation of the binary bit pattern you will be using is 15 (binary 1111). Outputting information is easy, and inputting is just as easy. If you actually want to get information into the computer, you will be using the 5 status lines. Reading the bit pattern of a port is done using the INP function. This function is used in the following way:
[variable]=INP([port])
So if we wanted to get the current status of the status lines (port 889) we would use:
PortNum%=INP(889)
would then contain the decimal representation of the binary bit pattern present at the 5 status lines. If you try this and get 31 (11111) with nothing connected to the port don't be surprised. When there is nothing connected to the input of a TTL logic chip, a high input is usually assumed.
PortNum%
Not only can you perform inputs on ports actually designed for inputting, but you can also use INP to read the status of an output port. For example:
PortNum%=INP(888)
The above would set PortNum% to the current value of the data lines (port 888). We can prove this by doing the following:
OUT 888, 56 PortNum%=INP(888) PRINT PortNum%
If all is well, the number 56 will appear on the screen. Now that we know the INP function we can use it to solve the problem of keeping the state of one bit while changing the state of another. For that we will define a subroutine that uses both functions:
SUB OutPort(PortAddress%, OutNum%) PortState% = INP(PortAddress%) PortNum% = PortState% + OutNum% OUT PortAddress%, PortNum% END SUB
Note how the sub adds the current port state to the number we send it. This has the effect of keeping all previous bits at the same state they were in, but either turning on or off the bit or bits represented by the number we pass to the sub. This also requires a change in the way the function is used. To turn on bit 1, we would:
OutPort 888, 1
This example assumes a current port status of 0 (00000000). If bit 1 is already high, you will get unexpected results, so keeping track of the port is important. To turn bit 1 back off, we would:
OutPort 888, -1
Now this sub introduces a problem. How do we clear everything on the port as if we were doing OUT 888, 0? Sending 0 to the sub has no effect (adding or subtracting 0 will always give you the original number), so we will need to add a statement to specifically react to a 0. This done by a simple IF...THEN decision:
SUB OutPort(PortAddress%, OutNum%) PortState% = INP(PortAddress%) PortNum% = PortState% + OutNum% OUT PortAddress%, PortNum% IF OutNum% = 0 THEN OUT PortAddress%, 0
END SUB
The sub does all it's normal stuff, but also sets the port to 0 if a 0 was passed to it. This is a very easy to clear up a port if you create strange bit patterns by trying to turn a bit on twice. You may want to keep track of the state you expect the port to be and compare it to the actual state by using the INP function. If the two do not match, clear the port and reset all the the bits using your other variable. Now that we know a few useful functions with respect to output, we should look at a very useful input function. When using the port in software, you will very likely need to know the status of a single bit at one time or another. There are various ways of doing this, but I find the function below to be the most useful:
FUNCTION BitStatus(PortAddress%, BitYouWant%) AS INTEGER IF PortAddress% = 888 THEN NumOfBits% = 8 ELSE IF PortAddress% = 889 THEN NumOfBits% = 5 ELSE NumOfBits% = 4 REDIM PortBits(NumOfBits%) AS INTEGER PortNum% = INP(PortAddress%) FOR i = 1 To NumOfBits% PortBits%(i) = PortNum% MOD 2 PortNum% = FIX(PortNum% / 2) NEXT I BitStatus% = PortBits%(BitYouWant%) END FUNCTION
The function first decides how many bits it has to work with by looking at the address of the port. Note that in all other examples it was really irrelevant if you used decimal or HEX addresses. In this function you will need to change the numbers if you work in HEX. Now, back to how the function functions (he he he). After deciding how many bits there are in the port, it makes an array of the same number of elements. It then goes through a loop, performing integer division on the number returned from the port. It performs one division for each bit in the port. This is probably the easiest way to convert to binary, as BASIC has no built in decimal to binary function. Again, if you work in HEX you will have to adjust the function here. The function then assigns itself the value of the array element you specify with the BitYouWant% variable.
Well, that's it. The above is not limited to the parallel port. You can use it with any sort of interface that uses a standard I/O port. Of course, this code would not be ideal in controlling the serial port, as a lot of low level coding would be necessary. If you are interested, you can also have a look at Programming The Parallel Port In Visual Basic. Back To Home Page | Mail Me | Search