并行端口接口
如何从 .NET 和 C# 与并行端口进行接口。
引言
完成本文后,您将能够在您的 .net 应用程序中使用并行端口。并行端口曾是一个非常流行的接口,也是连接外部硬件的首选。在现代计算机中,您几乎找不到任何并行端口,但它在硬件世界中仍然存在。因此,今天您可能会编写一个使用高级技术的应用程序,但可能需要支持一些遗留系统。因此,即使在今天,也可能有人要求您编写一个用于连接并行端口的程序。
并行端口的不同模式
并行端口是一个流行的接口,它在 1994 年发布的 IEEE 1284 文档定义的几种模式下工作。这些模式是 SPP(标准并行端口)、EPP(增强并行端口)和 ECP(扩展功能端口)。EPP 模式主要由打印机使用。ECP 并行端口模式向后兼容 EPP 和 SPP。
要以任何模式配置并行端口,我们必须遵循标准定义的程序。在本文中,我将通过代码演示如何在 ECP 模式下配置并行端口。ECP 模式支持更高的数据速率。
并行端口 ECP 模式
在 ECP 模式下,我们有 3 个基本寄存器:数据、控制和状态寄存器。除了这些之外,ECP 模式还有额外的软件寄存器,包括扩展控制寄存器、配置寄存器、数据寄存器和 FIFO 寄存器。我们需要使用这些寄存器来处理中断 I/O、DMA 和其他各种任务。我们可以通过内存映射地址在程序中访问这些寄存器。
正如我们所知,在硬件世界中,内存和端口是通过地址访问的。不同的地址分配给不同计算机上的并行端口,通常并行端口地址是 378hex,这是基地址。此端口地址可以从计算机 BIOS 中找到。数据端口可以使用此基地址访问。类似地,状态端口和控制端口可以通过分别将基地址加 1 和 2 来访问。要访问 ECP 软件寄存器,我们需要在基地址上加上 400Hex 来获取数据 FIFO。
我如何访问并行端口寄存器
要在我们的程序中访问所有这些寄存器,有几种可用的选项,例如开发并行端口的设备驱动程序,或者通过 Windows API 或其他库进行访问。在本文中,我使用了一个第三方库。
TvicPort.dll 是 Entech Taiwan 公司提供的一个用于处理并行端口的库。此库可以从 Entech Taiwan 网站免费下载。该库为我们提供了访问并行端口的函数。该库提供了我们可以与并行端口寄存器交互的方法。我们在应用程序中使用此库将并行端口配置为 ECP 模式,并用于与外部外围设备进行数据传输。
使用代码
为了配置并行端口并将其用于数据传输,我开发了两个类。一个类是 Entech Taiwan 提供的 DLL 文件的封装器,另一个类用于配置。
封装 DLL 库的类
为了编写封装器,我使用了 .net 的平台调用功能。我使用了 .net 类的 DLLImport
属性。DLLImport
用于访问扁平 DLL。在本例中,它是 Entech Taiwan DLL。通过使用这个封装类,我们可以处理并行端口的任何寄存器。下面是封装器中的一个代码片段
[DllImport("TVicPort.dll", EntryPoint = "OpenTVicPort", ExactSpelling = false, CharSet = CharSet.Unicode, SetLastError = true)] public static extern uint OpenTVicPort();
完整的封装器的类图是

第二个类主要用于配置以及数据读取和写入。
配置类
配置类定义了如何在任何模式下配置并行端口,特别是 ECP 模式。此类还演示了我们如何向并行端口读取和写入数据。
在此类的代码中,您将观察到我如何使用封装器来配置并行端口。
让我们看一个用于打开并行端口的类的代码
public void OpenEcpPort() { PPort.OpenTVicPort(); InitializeParallelPort(0x378); SetParEcpMode(); DirPeripheralToPc(); }
正如我在开头提到的,我将使用并行端口的 ECP 模式。因此,在此方法中,可以看到端口已初始化,然后将并行端口的模式从 SPP 更改为 ECP。因为并行端口的默认模式是 SPP。由于我将此应用程序用于连接外部设备或外围设备,并且该外围设备正在发送数据,因此我在 DirPeripheralToPC()
方法中将并行端口设置为从外围设备向 PC 传输数据。
让我们看以下代码
public void SetParEcpMode()
{
byte PortData;
PortData = PPort.ReadPort(parallelEcrRegister);
PortData = (byte)( (((int)PortData) & (0x1F)) | (((int)ecpMode) << 5) );
PPort.WritePort(parallelEcrRegister,PortData);
}
在上面的代码中,您可以看到我如何使用封装类访问并行端口寄存器。所有这些配置步骤都可以从 IEEE 标准中读取。它们提供了详细的描述。我只是实现了这些标准的描述。
类似地
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;
}
您可以看到我如何使用封装类配置并行端口。所有详细信息、地址寄存器和其他方法都可以在 IEEE 1284 标准中找到。您可以专注于实现,并下载本文中的代码并在您的应用程序中使用。作为参考,您可以查阅并行端口标准文档。
为了演示这两个类的用法,我包含了一个主程序,代码如下
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(); }
数据采集方法
您将编写的大部分应用程序都与使用并行端口的数据采集有关。在这里,我将讨论一些数据采集技术。基本上有三种数据采集技术:1) 轮询法 2) 中断 I/O 3) 直接内存访问 (DMA)。
轮询法
在数据采集的轮询方法中,采集程序会不断检查端口或地址是否有数据,如果有数据则读取数据,否则再次检查数据。这种方法的优点是它非常简单易用。但缺点是,如果您使用的是 PC,其中一个线程将完全忙碌;如果您使用的是微控制器,它将消耗更多电力。
中断 I/O
在中断 I/O 中,我们将设备配置好(例如,在本例中是并行端口),以便在数据可用时立即触发事件或中断。然后,我们的采集程序会处理这个中断来采集数据。与轮询方法相比,这是一种非常高效的数据采集方法。使用这种方法,您的线程或进程不会卡住,并且只会在数据可用时被调用。
直接内存访问
在直接内存访问中,我们将设备(如并行端口)配置为分配一块内存空间,外部外围设备可以直接向该空间写入数据,而不会中断处理器或线程。这样,采集程序就可以随时检查该内存空间并读取数据。这是一种极其高效的方法,允许您使用并行端口处理每秒超过 2MB 的数据速率。
如果您想要更高的数据速率,请选择 DMA,因为在其他方法中,处理器会参与其中。此外,它还取决于操作系统何时将处理器分配给您的进程。如果由于操作系统策略导致延迟,您可能会丢失一些数据。
您可以使用此处提供的库来使用轮询方法。要使用中断 I/O,您将必须配置并行端口。并行端口的 FIFO 大约是 16 字节,所以在选择中断 I/O 或轮询方法时,您需要牢记这一点。
如何部署
您可以为客户端部署 2 种方式。一种是将 DLL 库复制到可执行文件所在的同一目录中。为此,您需要在解决方案资源管理器中将文件(Entech Taiwan Dll)的属性设置为“复制到输出目录”为“始终”或“如果较新”。
第二种方式是将 DLL 文件复制到 Windows 系统目录。批处理文件已附加到本文。批处理文件的命令如下
copy TVicPort.dll %windir%\System copy TVicPort.sys %windir%\System32\Drivers
参考文献
- Entech Taiwan 库 (http://www.entechtaiwan.com/dev/port/index.shtm)