4
\$\begingroup\$

First of all, I have searched the internet all day long, including here on stackexchange, and couldn't find a clear solution. Only ambiguous answers and dead links.

  • Let's start with what I have: my PC has a motherboard from 2007, with an onboard parallel port. I bought a parallel port connector and soldered a wire to pin 2 and 25 ( first data pin and ground). I've put an appropriate resistor and an LED.
  • I started with the idea of using Processing first. After a bit of searching I found the PortIO library. I installed it and tried the blinking example. No success. The program seems to work( I inserted a print("Blink!"); after every delay and it displays the message), but the LED doesn't light up. I have to mention that, when I restart the computer, the LED briefly lights up. So the port is working, but I can't control it.
  • Then I moved to the idea of using C++. As I searched I found out that newer versions of Windows severely limit program access to hardware. Well, I found out about inpout32.dll, and downloaded it from this page(Binaries only - x86 & x64 DLLs and libs).
  • It seems the driver successfully installed, but I can't find out how to use the files. I use Visual Studio 2012, but I'm not really accustomed to working with external libraries and dlls. Where do I have to put the inpout32.dll, inpout32.h and inpout32.lib files and how do I link them?

And the biggest question is this: How do I actually use inpout32.dll? I can't find any example! It's either for Basic or C#, or even more frustrating, dead links! For starters, I'd Like to simply turn on and off the LED. Then I can figure out more complicated projects.

\$\endgroup\$
  • \$\begingroup\$ If you have a driver which lets you do raw output writes, you'll need to find the address of the port's data register. Typically that would be 0x378, 0x3bc, or 0x278. You may be able to find this from bios-like settings before boot, or perhaps from the device manager under windows. For a more portable and future-proof solution, consider a USB I/O chip or microcontroller - but beware the USB latency! \$\endgroup\$ – Chris Stratton Jun 16 '13 at 16:51
  • \$\begingroup\$ I know the "starting" adress is 0x378. But I don't know how to use that in C++. I can't find anywhere a reference for what functions I have to use to set the outputs to HIGH or LOW. I am aware of microcontrollers, but future-proof doesn't interest me for the moment. \$\endgroup\$ – Azurium Jun 16 '13 at 18:55
  • \$\begingroup\$ You would probably have to use one of these I/O libraries you mention, to set the value of port 0x378 to the sum of tge bit positions you want on. \$\endgroup\$ – Chris Stratton Jun 16 '13 at 23:21
  • \$\begingroup\$ You should try stackoverflow for this, I bet there are at least a few windows driver developers than can answer this easily. \$\endgroup\$ – apalopohapa Oct 4 '13 at 19:39
4
\$\begingroup\$

First off getting access to the parallel port in Win7, Vista and even WinXP is a major effort. Microsoft took away the ability for normal user code to be able to directly access the hardware registers. Instead they virtualized the accesses and if you try to do they they normally appear to have executed but they do not end up touching the hardware. To get access some special device driver solutions were devised, InpOut32.DLL is one example, that let user code indirectly access the port because the driver runs in system mode. I have previously used InpOut32 for some experiments and found that it adds quite a bit of latency to the accesses such that even on rather high speed machines the fastest available toggle rate of parallel port pins was on the order of less than 22KHz. When I used it I was coding in an unmanaged coding environment.

When you start writing code in something like VS2012 using managed code under Microsoft's .NET framework you have to jump through a lot of hoops to get add-on drivers such as InpOut32 to work (and it is not even certain that that particular driver is even workable in Win7's 64-bit environment). I have not attempted it in my current 64-bit environment because it is just not worth the effort to try to eek it into functionality because there is an additional loss of performance when calling an unmanaged driver from managed user code. One's time is much more well spent using one of the multitude of USB choices available to get access to external I/O via a USB bridge I/O device.

[EDIT: Added USB Port Output Idea]

One really easy little board that you can build into project and connect to a PC with a Mini-B USB cable is the USB Bit Whacker from Sparkfun Electronics. This little board shows up on the PC as a virtual Comm port and is able to accept very simple text commands that will toggle the outputs on and off or monitor the inputs.

enter image description here

\$\endgroup\$
  • \$\begingroup\$ I can't believe how hard this is. I have even found a Python solution, but, as above, no success. It's the pyParallel module, but they specify on its page that the "giveio" driver must be installed for accessing the hardware. Searching for this(they don't provide a link) turned out a single site that gives a download. Tried installing it and it says it fails( it's probably for 32 bit (-_-). How the heck does an old printer work if all of this is so restricted? If it doesn't, why did they put a parallel port on the motherboard in 2007?! \$\endgroup\$ – Azurium Jun 17 '13 at 22:39
  • \$\begingroup\$ Printer drivers are written to run in the system mode. As such they are allowed access to the parallel port hardware if it is found present. Parallel ports persisted for quite a while on new motherboards to allow support for legacy printers but are harder to find on new product today. There is a really good technical reason why the conventional parallel port was dropped. Back when the features for the extended parallel port modes were added there were extra port addresses added to the groupings for the LPT1, LPT2 and LPT3 port ranges. These added ports were added way outside (continued) \$\endgroup\$ – Michael Karas Jun 18 '13 at 0:31
  • \$\begingroup\$ (continued from above) the normal legacy range for each group. This made a complete mess out of I/O port mapping that is done in a dynamic assignment process that is used for PCI / PCIe plug and play setup. There is limited I/O space available in the first place and the havoc created by the enhanced parallel ports was 100% completely incompatible with the idea that any device should consume a single contiguous range of I/O port addresses that is as small as possible. So as you can see it was a very good thing from the hardware architecture standpoint to purge the parallel port. \$\endgroup\$ – Michael Karas Jun 18 '13 at 0:37
  • \$\begingroup\$ My suggestion to you is to either give it up and move on to USB external expansion techniques OR to step back in time and use your older motherboard's parallel port under a DOS or Win98 boot. For an example of a very simple little USB device that can give you every thing you need to toggle LEDs and look at switches please see my answer above. \$\endgroup\$ – Michael Karas Jun 18 '13 at 0:45
  • \$\begingroup\$ Thank you for the suggestion, that little guy sure looks interesting! But would it be amusing to tell you that I actually own an Arduino Uno? I'm just stubborn like that. I saw the parallel port as a simpler way to interface complex programs with hardware. It's true that Arduino offers much more I/O functionality, like analog input and PWM, but for simple I/O switching, if not for these restrictions, the Parallel port clearly wins in my vision. You have to couple Arduino with Processing, so already you need 2 programming environments. (well, ard. is based on proc., not a big diff. I suppose). \$\endgroup\$ – Azurium Jun 18 '13 at 11:00
2
\$\begingroup\$

Try this link: http://www.winsoft.sk/products.htm

Use their IOPort product. I have used this driver often on XP with C++ Builder and it just doesn't get any easier. For example, you can write to either the data or control lines like this where data_addr is typically 0x378 and

status_addr = data_addr+1;
ctrl_addr = data_addr+2;
IOPort1->Port[data_addr] = data_value;
IOPort1->Port[ctrl_addr] = ctrl_value;

Its been a while since I've used this, but I think you have to set one of the ctrl bits before you can read the data_addr. I believe the ctrl lines are write only and the status line are read only.

Just in case, here is a pretty good article on using the printer port. http://et.nmsu.edu/~etti/fall96/computer/printer/printer.html Pay particular attention to the 330 Ohm pull up resistors they show. They are a must use.

Also pay attention to bit 5 on the ctrl port. It controls whether you are reading or writing the 8 data bits.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.