## Tuesday, April 8, 2008

### Parallel Port as IO

Parallel Port can be used to control some digital devices and sometimes, it can also be used as IO for simple projects. I even found some systems that uses parallel port of an Industry PC to control LCD module. In fact, a Parallel Port has a lot of I/O and they can be used together with Relays and Transistors to control motors and light bulbs, etc. Last time, I helped one of my friends to controls 24 running light bulbs using a parallel port and Solid State Relays. A Parallel Port can have maximum of 12 outputs ( 8 data lines and 4 control lines). But you can demultiplex them according to your needs. It has 5 Inputs lines. If you can also use 8 Data lines as inputs (in later parallel port), there can be up to 13 inputs. Parallel Port has 5 Modes and you can see more details at here. A PC normally has a Parallel Port. If you don't have one, you can easily buy an IO card with a parallel port.

### Hardware

The following figure shows a Female 25 DB connector of a PC.
Wire lines in a parallel port can be differentiated into three groups.
1. Data lines
2. Control lines
3. Status lines
They are controlled by their corresponding registers.
Control lines can be used as outputs and Status lines can be used as inputs. Data lines can be used as inputs and outputs. If you want to use data lines as inputs, you need to enable Bidirectional data transfer first. Set bit 5 -"Bidirectional" bit of the control register to enable it. See the following table for definition of each pin.
----------------------------------------------------------|Pin No |Signal Name |Direction |Register -bit |Inverted |----------------------------------------------------------| 1.... | nStrobe....| Out......| Control-0....| Yes ....|| 2.... | Data0......| In/Out...| Data-0.......| No......|| 3.... | Data1......| In/Out...| Data-1.......| No......|| 4.... | Data2......| In/Out...| Data-2.......| No......|| 5.... | Data3......| In/Out...| Data-3.......| No......|| 6.... | Data4......| In/Out...| Data-4.......| No......|| 7.... | Data5......| In/Out...| Data-5.......| No......|| 8.... | Data6......| In/Out...| Data-6.......| No......|| 9.... | Data7......| In/Out...| Data-7.......| No......|| 10... | nAck.......| In.......| Status-6.....| No......|| 11... | Busy.......| In.......| Status-7.....| Yes.....|| 12... | Paper-Out..| In.......| Status-5.....| No......|| 13... | Select.....| In.......| Status-4.....| No......|| 14... | Linefeed...| Out......| Control-1....| Yes.....|| 15... | nError.....| In.......| Status-3.....| No......|| 16... | nInitialize| Out......| Control-2....| No......|| 17... | nSelect-Printer| Out..| Control-3....| Yes.....|| 18-25 | Ground.....|-.........| - ...........| - ......|----------------------------------------------------------

IBM PC has defined IO addresses for data register, control register and status register. The following table lists their IO addresses.

---------------------------------------------------| Register........| LPT1 | LPT2 |---------------------------------------------------| Data Register...| 0x378| 0x278|| Status Register.| 0x379| 0x279| (baseaddress + 1)| Control Register| 0x37A| 0x27A| (baseaddress + 2)---------------------------------------------------

For example, if you write 0x00 at IO address 0x378, data register of LPT1 will be 0x00 and the pin number 2 to 9 of DB25 connector that is connected to the data register will output 0V. Similarly, if you write 0xFF to IO address 0x378, bit 0 to bit 7 of data register will become 1 and pin 2 to pin 9 will output +5V.
Pin 1, 14, 16, and 17 are connected to control register at IO address 0x37A. But pin 1, 14, 17 are inverted outputs and pin 16 is non-inverted outputs. For an inverted outputs, it will output +5V if you write 0 and it will output 0V if you write 1 to the corresponding bit.
Status register at IO address 0x379 is input and you can read the status of pin 10, 11, 12, 13 and 15. Pin 11 is inverted input and the rest are non-inverted inputs. For a non-inverted input, +5V at input pin will appear as 1 and 0V will appear as 0 in the status register.

### Circuit Connection

A cable with a Male 25DB connector can be used to connect the PC with a parallel port and the other side of the cable can be used to connect inputs and outputs.
As an example, data pin 2 to 9 and control pin 1,14, 16, 17 will be used as outputs and status pin 10, 11, 12, 13 and 15 will be used as inputs. Therefore, outputs will connect to LEDs and inputs will connect to switches as shown in the following figure.
In the following figure, data pins are used as both inputs and outputs. For simplicity, they will be used as outputs only in our example.
You can use a multimeter to measure which pin connects to which wire. In some cables, all wires have same color. But for my cable, I found them as
1. Black
2. Black/white
3. Brown
4. Brown/white
5. Red
6. Red/white
7. Red/black
8. Orange
9. Orange/white
10. Orange/black
11. Pink
12. Pink/black
13. Yellow
14. Yellow/black
15. Green
16. Green/white
17. Green/black
18. Light Green
19. Blue
20. Blue/white
21. Magenta
22. Magenta/white
23. Grey
24. Grey/black
25. White
If you have set up LEDs and switches as above, you need to write a program to control them.

### Programming

In Windows 98 and Windows Me, we can control the port directly using C program functions such as "InportB" and "OutportB" in Turbo C and Borland C, and "_inp" and "_outp" of VC++. They are defined in "conio.h". But for Windows NT/2000/XP, we cannot control directly and we need to use a library file such as "inpout32.dll". You can get it from http://logix4u.net/inpout32_source_and_bins.zip. And put the "inpout32.dll" file in "C:/windows/system32/" folder. This example is demonstrated for Windows XP using Visual Basic 2005. But it is essentially the same for Visual Basic 6 also.
At first, create a new project in VB2005 by clicking File Menu ->New Project... . Choose Windows Application and click OK. Then add a module by clicking Tools bar -> Add New Item -> Add Module ... . Declare the following two lines of code in that module.

 'Inp and Out declarations for port I/O using inpout32.dll. Public Declare Function Inp Lib "inpout32.dll" Alias "Inp32" (ByVal PortAddress As Short) As Short Public Declare Sub Out Lib "inpout32.dll" Alias "Out32" (ByVal PortAddress As Short, ByVal Value As Short)

As in the following figure.
Add two buttons and two text boxes on the form.
To output the hexadecimal value in the text box to data pins when the first button is clicked, write the following code.
Out(&H378, Val("&H" & txtData.Text))
The first argument of the Out function is IO address. It uses IO address 0x378 to write to data register. The second argument is the value to write. To read the text box input as hexadecimal value, "&H" is appended in front of it.
When you click the second button, the value of the status pins will be read and displayed in the text box beside it. To read the status register at IO address 0x379, write the following code.
 txtStatus.Text = Hex(Inp(&H379))

The argument of Inp function is the IO address to read. The read value is converted to hexa string using Hex function and is displayed in the text box.

Reference:
http://logix4u.net/Legacy_Ports/Parallel_Port/A_tutorial_on_Parallel_port_Interfacing.html