I/O 端口编程(并行端口)读/写 + VB.NET 监控系统






4.88/5 (45投票s)
使用 VB.NET 进行输入输出端口访问和监控系统以及并行端口入门

Contents at a Glance
- 引言
- 与并行端口通信
- 并行端口和寄存器的寻址
- Inpout32.dll 简要说明
- 读取引脚(状态寄存器)或外部值
- 向引脚(数据寄存器)写入
- 如何点亮 LED
- 连接并行端口设备的更高级方法(紧凑型 8 通道输出驱动器)
- 监控系统和示例应用程序是如何运行的?
- 参考文献
引言
并行端口,也称为打印机端口,是用户可用于与外部电路或自制硬件设备通信的最易用的硬件之一。大多数人认为与外部电路接口很难,并且从未找到解决方案。然而,在本文中,我将试图说服您,与其他外部设备进行端口通信非常容易,并且只需要记住一些技巧!
我还将讨论一个可以用很少的资源开发的示例监控应用程序。它非常简单,任何阅读本文的人都可以在家中使用。然后,我将介绍串行端口编程,这将是我在 The Code Project 上的下一篇文章。在该部分中,我将说明串行数据传输的一些基本知识以及如何使用更高级的串行端口而不是并行端口。
我提供的应用程序是使用 Visual Basic .NET 开发的,它使用 inpout32.dll 进行直接端口访问。在 Windows XP 和 NT 版本中,不允许直接访问端口,因此我们需要一个驱动程序才能直接与端口通信。因此,我们使用的是免费驱动程序 inpout32.dll,您可以在此处找到它。
警告
您计算机上的并行端口很容易损坏!因此,请自行承担使用所有示例代码的风险。所有这些示例程序和电路都经过了彻底测试,它们绝不会导致您损坏硬件或计算机。我从未遇到过如此糟糕的事件!但是,请谨慎使用这些程序……
与并行端口通信
并行端口通常是一个 25 针母头端口,通常用于将打印机连接到计算机。许多极客也将其用于将自己的设备连接到 PC。在使用 PC 的并行端口时,还有一些事情需要记住。它只能负载 2.5mA 和约 2.5 伏。在与外部设备接口时,最好使用光电耦合器或 ULN2803。
如果您只是想通过打印机端口点亮一个 LED,请尝试在之间连接一个 330 欧姆的电阻。在编程打印机端口时,还有一些更有用的信息需要考虑:通常的打印机端口是一个 25 针母头 D 形端口,它有几个寄存器。寄存器是一个可以写入值并检索值的地方。有不同类型的寄存器,称为数据寄存器、控制寄存器和状态寄存器。
数据寄存器
这是允许用户将值写入端口的寄存器。简单来说,这些引脚可用于在数据寄存器中输出特定值。您也可以更改特定引脚的电压。这些被称为输出引脚。总共有 8 个输出引脚可用,范围从 D0 到 D7。
状态寄存器(引脚)
这些被称为输入引脚或状态寄存器,可以保存外部世界提供给并行端口的值。因此,该端口充当读取器,有 5 个引脚用于输入。引脚范围是 S4 到 S7。
控制寄存器(引脚)
此寄存器可用于双向:它允许用户向外部世界写入值,也允许从外部世界读取值。但是,您需要记住,大多数控制引脚的工作方式是反向的。您可以在引脚顶部看到一个破折号。引脚范围是 C0 到 C3。接地引脚用作中性;这些引脚用作电池中的(-)。如果您要连接设备到并行端口以进行读取或写入,您必须使用一个或多个接地引脚和读/写引脚才能工作。例如,如果您要点亮一个 LED,那么您必须将 LED 的(-)连接到接地引脚,将 LED 的(+)连接到输出引脚。对于读取目的,使用相同的机制。
· 8 Output pins [D0 to D7]
<!--[if !supportLists]-->
· 5 Status pins [S4 to S7 and S3]
<!--[if !supportLists]-->
· 4 Control pins [C0 to C3]
<!--[if !supportLists]-->
· 8 ground pins [18 to 25]

并行端口和寄存器的寻址
端口寻址在端口编程中非常重要,因为它是程序连接到外部电路或设备的门。因此,我想解释所有可用的端口地址。
在普通的 PC 中,并行端口地址可以是下面给出的地址之一,但根据 BIOS 设置和其他一些问题,并行端口地址可能会有所不同。但是,它始终位于这些地址范围之一。
<!--[if !supportLists]-->
· LPT1 03BC (hex) 956(decimal)
<!--[if !supportLists]-->
· LPT2 0378(hex) 888(decimal)
<!--[if !supportLists]-->
·
<!--[endif]-->
LPT3 0278 (hex) 632(decimal)
如上所述,这些是并行端口常用的地址范围。现在您可能想知道我们如何与它们中的每一个通信以及它们如何工作。这很简单!上面提到的每个地址范围都有自己的数据寄存器、控制寄存器和状态寄存器地址。因此,如果您想访问端口 888 的数据寄存器,那么数据寄存器也是 888。但是,如果您想访问状态寄存器,则在 888 上加 1 = 889,这就是 888 基并行端口的状态寄存器。要访问控制寄存器,您需要再加 1,这样就是 890,这就是 888 基并行端口的控制寄存器。如果您的并行端口地址不同,请相应地执行此操作以查找其对应的寄存器。
还有一种简单的方法可以检查您计算机的并行端口地址。您可以从设备管理器中了解并行端口的 I/O 地址。首先,打开设备管理器(开始 -> 设置 -> 控制面板 -> 系统 -> 硬件 -> 设备管理器)。然后从“端口 (COM & LPT)”部分选择您感兴趣的并行端口。使用鼠标右键,您可以获得一个菜单,从中选择“属性”。当您完成这些步骤后,您将看到一个类似于此的对话框。找到列表框中的第一个项目,它的值是 0378 – 037F,所以这是打印机端口的地址范围。数据寄存器地址是十六进制的 0378 或十进制的 888。

Inpout32.dll 简要说明
在这里,本文中,我们使用一个名为 inpout32.dll 的第三方工具来连接您 PC 上的端口。我们使用它是因为在基于 Windows NT 的版本中,所有低级硬件访问都被禁止,需要单独的 I/O 驱动程序。当我们读取端口状态时,我们必须获得该第三方应用程序的支持。
在 inpout32.dll 中,包含了激活和运行该系统驱动程序所需的所有系统驱动程序和小型工具。因此,我们不必过多考虑或思考这是如何发生的;它将为我们完成所有工作……
既然我们使用 DLL 文件与硬件通信,我们就必须知道该特定文件为用户提供的链接,或者该特定文件的入口点。在这里,我将逐一描述所有入口点。
用于读取的 DLL 入口
Public Declare Function Inp Lib "inpout32.dll" Alias "Inp32" _
(ByVal PortAddress As Integer) As Integer
用于输出值的 DLL 入口
Public Declare Sub Out Lib "inpout32.dll" Alias "Out32" _
(ByVal PortAddress As Integer, ByVal Value As Integer)
Inp32
函数可用于读取 PortAddress
参数提供的任何地址的值。此外,Out32
函数专门用于向数据端口写入值。下面可以找到关于这两个函数的详细说明。
读取引脚(状态寄存器)或外部值
Inp32
是 inpout32.dll 中定义的通用函数,用于与您计算机上的各种硬件地址通信。此函数包含在 DLL 中,因此可以使用任何支持 DLL 导入函数的编程语言来调用此文件。
在这里,对于这个示例应用程序,我使用了 Visual Basic .NET,因为任何了解 .NET Framework 一点的人都可以使用它。读取并行端口状态非常简单。我将逐步解释一切,但请记住,在示例代码中,我假设状态寄存器的地址是 889 或十六进制的 0x379h。
- 打开 Visual Studio .NET(我在 .NET 2005 版本中制作了这个)。
- 创建一个新的 Visual Basic .NET Windows 应用程序。
- 转到“项目”菜单,然后单击“添加新项”。然后从列表中选择“模块”项。
- 为您要创建的新模块键入任何合适的名称,例如 porting.vb。
- 在模块文件中,应该有一些这样的文本
Module porting Public Declare Function Inp Lib "inpout32.dll" _ Alias "Inp32" (ByVal PortAddress As Integer) As Integer End Module
- 转到您的表单并添加一个新的文本框。然后添加一个命令按钮,并在命令按钮的单击事件中粘贴此代码
'Declare variables to store read information and Address values Dim intAddress As Integer, intReadVal As Integer 'Get the address and assign intAddress = 889 'Read the corresponding value and store intReadVal = porting.Inp(intAddress) txtStatus.Text = intReadVal.ToString()
这只有在您刚刚创建的文本框名称为
txtStatus
时才能正常工作。 - 运行您的应用程序并单击按钮,文本应显示为 120 或某个类似值。然后,这就是您的并行端口的状态。
- 如果您想检查此应用程序是否正常运行,您只需要取一小段导线(屏蔽线或电路导线都可以),然后短接一个状态引脚和一个接地引脚。例如,状态引脚是 10、11、12、13、15,如果您短接第 10 个引脚和第 25 个(接地)引脚,那么文本框中的值将是 104。如果您短接其他引脚,如第 11 个和第 25 个,那么文本框的值将是 88 或类似值。
现在您可以看到所有的力量都在您手中。如果您是一个有创造力并且精通电子学的人,那么可能性是无限的……
注意!
在运行和编译此应用程序之前,请从本页下载 inpout32.dll 并将其复制到项目目录的 Bin 文件夹中,即生成可执行文件的位置,这样 DLL 应该在同一目录中才能工作。或者,您可以将 DLL 文件复制并粘贴到您的 Windows 系统目录中,这样您就不需要在应用程序路径中包含该文件。您只需要遵循一个指南。
向引脚(数据寄存器)写入
在向数据寄存器写入数据时,您必须遵循相同的规则。基础没有区别!正如您在上面的上下文中学习到的,在这里也做同样的事情,只有一些区别。我将向您解释它们是什么,但请记住,在示例代码中,我假设数据寄存器的地址是 888 或十六进制的 0x378h。
- 转到“项目”菜单,然后单击“添加新项”。然后从列表中选择“模块”项,与上面相同。
- 为您要创建的新模块键入任何合适的名称,例如 porting.vb。
- 在模块文件中,应该有一些这样的文本
Module porting Public Declare Sub Out Lib "inpout32.dll" _ Alias "Out32" (ByVal PortAddress As Integer, ByVal Value As Integer) End Module
- 转到您的表单并添加一个命令按钮。在命令按钮的 Click 事件中,粘贴此代码
intVal2Write As Integer 'Read the corresponding value and store intVal2Write = Convert.ToString(txtWriteVal.Text) 'porting is the name of the module porting.Out(888, intVal2Write)
这只有在您刚刚创建的文本框名称为
txtWriteVal
时才能正常工作。 -
运行您的应用程序并单击按钮,并行端口将根据您在文本框中输入的值在引脚上输出电压。
如何点亮 LED
现在来测试您输出的值。假设您将值 2 写入数据寄存器,并且您想知道哪个引脚输出 +5V。这很容易检查。数据寄存器从引脚号 2 开始,到引脚号 9 结束,所以有 8 个输出引脚。换句话说,它是一个 8 位寄存器。所以,当您向其数据寄存器写入 2 时,第 3 个引脚将是 +5 电压。您需要使用科学计算器将十进制 2 转换为二进制;那么值为 2(十进制) = 1 0(二进制)
,所以 1 0
意味着数据寄存器中的状态是 0 0 0 0 0 0 1 0
。
示例 2
如果您向数据寄存器写入值 9
,那么 9
的二进制是 0 0 0 0 1 0 0 1
。所以,+5V 可以从第 2 个引脚和第 5 个引脚获得。
二进制值 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
1 |
数据寄存器 |
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
实际引脚号 |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
示例 3
假设您向数据寄存器写入 127
。那么 127
的二进制是 0 1 1 1 1 1 1 1
,因此所有引脚都将是 +5V,不包括第 9 个引脚。
二进制值 |
0 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
数据寄存器 |
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
实际引脚号 |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
当您想点亮 LED 时,有一种特殊的方法将它们连接到数据寄存器。所以,您需要一些工具来连接。作为教程,我将解释如何只连接 1 个 LED。

在这里,您需要将接地引脚连接到任何从第 18 个到第 25 个的引脚。它们都是接地引脚,所以没有区别。输出引脚或 LED 的正极应连接到数据寄存器中的一个引脚。当您写入一个启用该特定数据寄存器引脚的值时,LED 将会亮起。
注意!
切勿连接消耗电压高于 LED 的设备,这会烧毁您的并行端口或整个主板。所以,请自行承担风险……!我建议您参考下面写的方法,如果您正在进行更高级的方法。如果您想打开和关闭电器,那么您显然需要使用继电器或高压三端双向可控硅。我建议使用继电器并通过我下面说明的方法连接它们。
连接并行端口的更高级方法
(紧凑型 8 通道输出驱动器)
如果您不满足于点亮 LED,并且渴望更进一步,那么请使用此方法将您所有的高级或更复杂的设备连接到并行端口。我建议您考虑使用 ULN2803 IC。这是一个 8 通道达林顿驱动器,可以使用它为高达 500mA 和 +9V 的设备供电。
在这里的图表中,您可以看到如何将一组 LED 连接到此 IC。还请记住,您可以将这些 LED 替换为任何支持高达 500mA 的设备,例如继电器或电磁阀,它们将平稳运行。

监控系统和示例应用程序是如何运行的?
我编写的监控系统非常小,只能在家中使用或个人使用。但是,如果您了解更复杂的安全系统是如何工作的,您可以使其更高级。在这里,应用程序有一个定时器,并且它始终检查状态寄存器的变化。如果发生变化,应用程序的状态将改变,并会相应地播放声音。
这可以用来检查您房间的门是否关闭。您所要做的就是将一个常闭开关放在门边,并将其放置在门打开时激活的方式。如果您不使用常闭开关,那么只需放置两层可以弯曲的薄金属片,并将它们放在门上。但是,这两层金属片在门关闭时应该能够造成短路。一层金属片应该焊接到屏蔽线(电路导线)上,然后连接到接地引脚。另一层金属片应该连接到并行端口的状态引脚。状态引脚是 10、11、12、13、15。
参考文献
我从 2000 年开始学习编程硬件端口。据我记忆,我大部分时间都从 Google.com 获取资源,并且我使用了在那里找到的链接……但是,请记住,创造力不能从网上搜索到。它应该在您的脑海里……所以要有创意,并支持社区……