Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Parallel Port Interfacing

4.14/5 (5 votes)
12 Nov 2013CPOL7 min read 46.2K   2.7K  
How to interface with parallel port from .NET and C#.

Introduction

After completing this article you will be able to use parallel port in your .net application. Parallel port was a very popular interface and was the default choice for interfacing with external hardware. In modern computers you will hardly find any parallel port but it still exist in the hardware world. So its possible that today you may be writing an application using advance technologies but you may required to support some legacy systems. Therefore even today someone may ask you to write a program for interfacing with parallel port.

Different Modes of Parallel Port

Parallel port is a popular interface and it works in several modes as defined in IEEE 1284 document published in the year 1994. These modes are SPP (standard parallel port), EPP (Enhanced parallel Port) and ECP (Extended capabilities port). EPP mode is mainly used by printers. ECP parallel port mode is backward compatible to EPP and SPP.

To configure the parallel port in any mode we have to follow the procedures define by the standards. In this article I am going to demonstrate through code how to configure parallel port in ECP mode. ECP mode support higher data rates.

Parallel Port ECP Mode

In ECP mode we have got 3 base register, data, control and status registers. Additional to these there are extra software register in ECP mode which are extended control registers, configuration registers, data registers and FIFO registers. We need to work with these registers to work with interrupt I/O, DMA and several other tasks. We can access these registers in our program with the help memory mapped addresses.

As we know in hardware world memory and ports are accessed by addresses. There are different addresses assign to parallel port in different computers usually parallel port address is 378hex which is base address. This port address can be find from the computer BIOS. Data port can be accessed using this base address. Similarly status port and control port can be accessed by incrementing the base address by 1 and 2 respectively. For accessing ECP software registers we need to add 400Hex in the base address to get data FIFO.

How can I access parallel port registers

To access all these registers in our program there are several options available such as developing a device driver for parallel port or accessing it through windows API or through some other library. In this article I have used a third party library.

TvicPort.dll is a library provided by Entech Taiwan Company to work with parallel port. This library is free to download from Entech Taiwan website. This library provides us functions to access parallel port. This library provides us the methods through which we can interact with parallel port registers. We use this library in our application to configure parallel port in ECP mode and for receiving and transmitting data to and from external peripheral.

Using the code

In order to configure the parallel port and use it for data transfer I have developed two classes. One class is solely a wrapper around the Entech Taiwan provided DLL file and the other class is used for configuration.

Class for Wrapping the DLL Library

In order to write the wrapper I have used platform invoke feature of .net. I have used DLLImport attribute of the .net class. DLLImport is used for accessing flat DLLs. In our case it is Entech Taiwan DLL. By using this wrapper class we can work with any register of the parallel port. One code snippet from the wrapper is given here:

[DllImport("TVicPort.dll", EntryPoint = "OpenTVicPort", ExactSpelling = false, CharSet = CharSet.Unicode, SetLastError = true)]
   public static extern uint OpenTVicPort();

And the class diagram for the complete wrapper is:

Second class is mainly used for configuration and data reading and writing.

Configuration Class

Configuration class defines how to configure the parallel port in any mode specially ECP mode. This class also shows how can we read and write data to parallel port.

In the code of this class you will observer how I am using the wrapper in order to configure the parallel port.

Let's consider the code from this class for opening the parallel port:

public void OpenEcpPort()
{
  PPort.OpenTVicPort();
  InitializeParallelPort(0x378);
  SetParEcpMode();
  DirPeripheralToPc();
} 

As I mentioned in the start I will be using the ECP mode of the parallel port. Hence in this method one can see that port is initialized and then change the mode of the parallel port from SPP to ECP. Because default mode of parallel port is SPP. Since I am using this application for interfacing with external device or peripheral and that peripheral is sending data therefore I direct the parallel port to accept data from peripheral to PC in the method DirPeripheralToPC().

Let's consider the following code :

C#
public  void SetParEcpMode()
{
   byte PortData;
   PortData = PPort.ReadPort(parallelEcrRegister);
   PortData = (byte)(  (((int)PortData) & (0x1F)) | (((int)ecpMode) << 5)  );
   PPort.WritePort(parallelEcrRegister,PortData);
}    

In the above code you can see that How I am accessing the parallel port registers using the wrapper class. All of this configuration steps can be read from the IEEE standard. They have give the detail description. I am just implementing the description of those standards.

Similarly:

C#
public void DirPeripheralToPc()
{
     byte PortData;
     PortData = 0;
     PortData = SetControllPortBit(0);
     PortData = SetControllPortBit(3);
     PortData = SetControllPortBit(1);
     ClearControllPortBit(2);
     PortData = SetControllPortBit(5);
} 
public byte SetControllPortBit(byte BitNo)
{
     byte PortData;
     PortData = ReadControllPort();
     PortData = SetBit(PortData,BitNo);
     WriteControllPort(PortData);
     return PortData;
}
public void WriteControllPort(byte PortData)
{
     PortData = (byte)(PortData  ^ 0x0B);
     PPort.WritePort(0x378+2,PortData);
} 
public byte  ReadControllPort()
{
     byte PortData;
     PortData = PPort.ReadPort(0x378+2);
     PortData = (byte)(PortData ^0x0B);
     return PortData;
} 
public byte SetBit(byte Byte,byte BitNo)
{
     Byte =(byte) (Byte | (1<< BitNo));
     return Byte;
}

You can see that how I am configuring the parallel port using the wrapper class. All the details and address registers and other methods you can find inside the IEEE 1284 standards. You can just focus on the implementation and download the code from this article and use it in your application. For reference you can refer to the parallel port standards document.

In order to demonstrate the use of these two classes I have included a main program and the code is:

 static void Main(string[] args)
{
  Console.WriteLine("Writing and reading single byte from Parrallel Port");
  ParallelPort aPort = new ParallelPort();
  aPort.OpenEcpPort();
  Console.WriteLine("Writing a single byte to parralel Port");
  aPort.WriteData(0x37);
  Thread.Sleep(100);
  Console.WriteLine("Read the data from parallel Port");
  if (aPort.TestFifoEmpty() != 1)
  {
    byte data = aPort.ReceiveData();
    Console.WriteLine("Write Data to Console" + data.ToString());
  }
 
  Console.ReadKey();
}

Methods of data acquisition

Most of the application that you are going to write is about data acquisition using parallel port. Here I am going to discuss some techniques of data acquisition. Basically there are three techniques when acquiring data: 1) Polling method 2) Interrupt I/O 3) Direct Memory Access (DMA) .

Polling Method

In polling method for data acquisition the acquiring program keep checking the port or address for data if data is available it reads out the data otherwise it again check for data. One benefit of this approach is that it very simple to use. But the disadvantage is that one of the thread will be fully busy if you are using PC or it will consume more power if you are using micro-controller .

Interrupt I/O

In interrupt I/O one configure the device, for example in our case parallel port, to raise the event or interrupt as soon as data is available. This interrupt is then handle by our acquiring program to acquire data. This is a very efficient approach for data acquisition compare to polling method approach. In using this approach your thread or process will not get stuck and will only be called when the data is available.

Direct Memory Access

In Direct Memory Access we configure the device, such as parallel port, to allocate a memory space at which outside peripheral can directly write the data without any interruption to the processor or thread. In this way acquiring program can check that memory space and read out the data whenever it wants. This is extremely efficient approach and allow you to handle data rate of more than 2 Mega bytes per second using parallel port.

If you want higher data rate go for DMA because in other approaches the processor is involve. As well as it depends upon the operating system when it allocates the processor to your process. If delay occurs due to the policies of operating system one may loose some of the data.

You can use polling method approach by using the library provided here. In order to use interrupt I/O you will have to configure the parallel port. FIFO of the parallel port in is of about 16 bytes so you will have to take this consideration in mind when going for interrupt I/O or Polling method.

How to deploy

You can deploy to client in 2 ways. One is by copying the DLL library in the same directory where your executable is there. For that you will have to set the property of the file(Entech Taiwan Dll) in solution explorer "Copy to output directory" to always or if newer.

Second is by copying the DLL file to windows system directory. The batach file is attached to this article. The batch file commands are given below

copy TVicPort.dll %windir%\System
copy TVicPort.sys %windir%\System32\Drivers 

References

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)