如何控制外设端口:在Linux 上用C 访问和写入并行端口。第一部分
在此页
- 术语定义
- 并口:
- 网络界面:
- 家庭自动化:
- 并口输出
- 寻址
- DMA 渠道
- 定义并行端口的内存地址
- 使用数据总线作为输出端口
- 示意图
- 真实电路
控制 PC 外围端口的最引人注目和新兴的用例之一是家庭自动化,这项技术为我们的家庭提供了无限的可能性。家庭自动化是一门具有社会性的技术学科。我们的方法是使用一些关键短语来改善生活质量、扩大沟通和自动化流程。所有这一切似乎都非常简单,但这个家庭自动化新世界内在的复杂性令人兴奋,让我们看看为什么。
出于多种原因,家庭自动化是一项复杂的活动。首先,对家用设备(传感器、智能电器、执行器...)的操作让您了解复杂的物理现象,例如机械量子或光电效应。此外,这些设备之一可以执行各种任务,而不仅仅是一个简单的任务。其次,谈论家庭自动化就是谈论由许多不同组件组成的系统,这些组件并不总是很容易交互(想象一个家庭安全系统,包括摄像机、存在检测器、通信设备、带有远程警告系统的警报器等) ……)。最后,也是最重要的,它是复杂的,因为它面临着技术系统与社会系统的自动化。
术语定义
并口:
并行端口是计算机和外围设备之间的接口,其主要特点是数据位一起传输,一次发送一个数据包字节。每个数据位的电缆或物理路径是通过形成 8 条线路的总线来实现的。通过并口,我们还可以控制外围设备,如灯光、电机等设备。
网页界面:
Web 界面允许用户通过 Web 浏览器控制他们的设备并与之交互。这可用于远程控制、图书馆管理、视觉反馈和许多其他事情。
家庭自动化:
它是所有能够实现家庭自动化的系统的自动化,提供能源管理服务、安全、福利和通信,并且可以集成在有线或无线室内和室外通信网络中。
如何在 C 中使用并行端口
对于我们的主要目的,基本的家庭自动化,我们将使用并行端口来演示我们如何写入(或读取)一些字节来控制简单的设备。 PC ECP Type 的并口有一个 DB25 型输出连接器,其原理图和信号如下图所示:
并口输出
根据Centronics标准,PC的并行端口由双向8个数据位通信总线以及协议的一组线组成。通信线的固定器具有写给他们的最后一个值,直到编写新数据为止,电气特性为:
- 高电平电压:3.3 至 5V。
- 低电平电压:0 V。
- 最大输出电流:2.6 毫安。
- 最大输入电流:24 毫安。
电压和电流可以馈入一组控制设备,如 LED、继电器和固态开关。需要这些缓冲器来关闭或打开具有较高功耗的元件。
寻址
标准并行端口的寻址很重要,因为它使用来自计算机的各种资源并用于识别目的。标准并行端口使用三个连续的地址,通常在以下范围之一:
3BCh 3BDh 3BEh 378h 379h 37Ah 278h 279h 27Ah
范围内的第一个地址是端口基地址,也称为数据寄存器或端口地址。第二个地址是端口状态寄存器,第三个是控制寄存器。EPP 和 ECP 为每个端口保留额外的地址。 EPP 在基地址 + 3 到基地址 + 7 处添加五个寄存器,而 ECP 在基地址 + 400h 到基地址 + 402h 处添加三个寄存器。对于 378h 的基地址,EPP 寄存器位于 37Bh 至 37Fh,ECP 寄存器位于 778h 至 77Fh。
DMA 通道
ECP 可以使用直接内存访问 (DMA) 将数据传输到并行端口。在 DMA 传输期间,CPU 可以自由地做其他事情,因此 DMA 传输可以带来更快的整体性能。为了使用 DMA,端口必须有一个分配的 DMA 通道,在 0 到 3 的范围内。
在 Linux 上访问物理端口
因为 PC 上的端口硬件直接由 Linux 内核控制,所以我们必须访问与并行端口总线相关的某些头文件。 GCC 编译器可以访问这些标头,始终牢记用户必须具有 root 权限以避免访问错误。这些标头是:
- stdio.h: The \standard input-output header\ (standard header I/O)是包含C程序设计语言标准库中的宏定义、常量、函数声明来执行操作的头文件、标准输入和输出,以及此类操作所需的类型定义。出于兼容性原因,编程语言C++(C派生)也有自己对这些函数的实现,用cstdio文件头声明。我必须使用的函数是 fprintf,如果有任何错误,它允许在终端窗口上打印。
- stdlib.h:通用编程语言C标准库的头文件,包含动态内存管理、进程控制等的C函数原型。它支持 C++,它被称为 cstdlib。我将使用的函数是在出现错误时退出
- unistd.h:提供对 POSIX 操作系统 API 的访问的头文件。在类 Unix 系统上,由 unistd.h 定义的接口通常主要由系统调用包装函数组成,例如 fork、pipe 和 I/O 原语(读、写、关闭等)。
- sys/io.h:这一系列函数用于执行低级端口输入和输出。 out*函数做端口输出,in*函数做端口输入; b-后缀函数是字节宽度,w-后缀函数是字宽; _p 后缀函数暂停,直到 I/O 完成。在这个系列函数中,我将使用 outb。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/io.h>在 Linux 中,访问和控制并行端口很容易,但是,必须高度考虑 root 访问权限。以上就是我们今天教程所需要的所有库。
定义并行端口的内存地址
一旦包含库,我们必须定义分配给并行端口的内存地址,如上所述,第一个并行端口的默认地址是 0x378。
#define base 0x378 /* parallel port base address */
如果您在尝试此地址时遇到任何问题,您应该尝试 0x278。
使用数据总线作为输出端口
对于第一部分教程,我将使用数据总线作为输出端口。在下一章中,我们将了解如何将其用作数据输入端口甚至混合端口。在下图中,我们可以看到通过限流电阻连接到并行端口的一组 8 个 LED 的控制,这些 LED 响应分配给地址 0x378 的值。电阻器的值可能从 100 欧姆到 300 欧姆不等,这部分很重要,因为如果我们不限制电流,我们可能会损坏端口。
原理图
真实电路
软件实施
出于我的目的,我将向您展示如何在端口中放置一些值,以及必须如何对这些值进行计时,这是一个非常简单的例程来向您展示它是如何工作的。
现在我将解释控制软件中使用的所有命令和单词:
- 第 1 步:判断用户是否具有访问端口的 root 权限。此条件命令的参数是 ioperm,它为端口地址基设置端口访问权限位。
if (ioperm(base,1,1))
- 第二步:如果用户没有足够的权限访问并口,将显示访问错误,程序执行结束。
fprintf(stderr, "Access denied to %x\n", base), exit(1);
- 第 3 步:如果访问被授予,则 for 循环将按照预定义的值为 LED 提供一系列开和关,以显示在端口中。我使用的计时函数是 sleep() ,它使调用线程休眠直到参数中的秒数过去。
w=0;
for (x=0; x=7; x++)
{
y=pow(2,w);
outb(y, base);
sleep(1);
w=w+1;
}
当代码处理通过access allowed line, fprintf(stderr, \Access denied to %x\n\, base), exit(1);, 并口的数据管脚就可以随意使用了和想象力。在我的例子中,我只采用一个简单的序列,从第一个到最后一个,间隔为一秒,使用基数 2 的幂。(参见视频链接)。然而,可能性是无限的,事实上,在不使用多路复用的情况下最多可以控制 8 个独立的输出,而使用多路复用输出可以增长到 255 种可能性。根据应用的不同,无论是在家庭自动化方面,我们都可以在不进行多路复用的情况下处理端口,放置适当的缓冲器来处理更高的电流负载,这将在稍后的另一个教程中进行处理。参考:
Martin H, Saez F. Domotica, Un Enfoque Sociotécnico。 2006 年 6 月。Fundación Rogelio Segovia para el Desarrollo de las Telecomunicaciones,Ciudad Universitaria,s/n 28040-Madrid,ISBN:84-7402-335-1。
Axelson J. 并行端口完成。 PC 并行打印机端口的编程、接口和使用。亚马逊公司 ISBN:0-9650819-1-5
Kerrisk M. Linux 编程接口。 Linux 手册页项目。书号 978-1-59327-220-3