I/O驱动

2024-07-11

I/O驱动(精选8篇)

I/O驱动 篇1

在计算机应用系统和控制系统的开发过程中,通常需要在Windows环境下,直接访问和控制具有特定功能的硬件设备。由于操作系统版本不同,其运行机制必然存在差异。在这里针对驱动程序的运行机制主要分为两类。一类是以前的Dos和Windows98系统,在这类环境下可以直接完成对I/O端口的读写;另一类是NT4.0以上版本Windows系统,在这类环境下,为了使系统变得更为安全,Windows对系统底层操作采取了屏蔽策略,不允许用户态的应用程序直接访问I/O端口,而是通过编写驱动程序,这样可以使用Kernel层设备驱动程序提供的各种服务间接地访问I/O,因此编写I/O设备驱动程序极为重要。

为了解决I/O设备驱动程序和不同结构操作系统的兼容性[3],微软公司在1997年提出了一种全新的Windows驱动程序模式(WDM),支持即插即用、电源管理和WMI技术,为存在于Windows 9x和Windows 2000操作系统中的设备驱动程序提供了统一的参考框架。

1 WDM系统函数

WDM驱动程序包含了许多子例程,操作系统通过调用相关例程来执行针对I/O请求包的各种操作[1]。WDM驱动程序可执行包中的内容如下:

1.1 基本驱动程序与设备操作

(1)DriverEntry例程负责初始化程序范围的数据结构和资源。

(2)AddDevice例程是被系统调用,进行初始化一个被枚举的新设备。

1.2 I/O控制

(1)StartIo例程进行串行处理,对IRP进行排队。

(2)AdaperControl例程负责执行DMA传输。

(3)OnInterrupt是一个中断服务例程。

(4)DPC是一个延迟过程调用例程。

1.3 派发功能函数

Dispatch为调度例程,负责处理应用程序与驱动程序之间的通信,包括Writer,Read等,开发人员必须选择特定驱动中需要的例程。

1.4 设备的创建和初始化

1)内核模式驱动程序没有main或WinMain,而是由I/O管理器根据需要调用一个驱动程序例程:(1)驱动程序被装入时;(2)驱动程序被卸出或系统关闭时;(3)用户程序发出I/O系统服务调用时;(4)共享硬件资源对驱动程序可用时;(5)设备操作过程中的任何时候。

2)相关内容:(1)所有驱动程序必须包含DriverEntry例程,进行驱动程序初始化。(2)利用AddDevice函数负责创建一个设备对象,并建立一个私有的设备扩展对象。(3)给出设备名并创建符号连接名或者注册设备接口。(4)初始化设备扩展和设备对象的标志位。(5)把新设备对象附着到设备堆栈中。

2 硬件的访问及资源分配

PnP管理器使用IRP来指导驱动程序启动、停止和删除设备,并查询驱动程序的设备,WDM是PnP驱动程序,必须具备PnP例程。IRP是DDK定义的一个数据结构。当驱动程序接收到PnP子码IRP_MN_START_DEVICE时,IRP堆栈列表内的两个字段AllocatedResourcesTranslated和AllocatedResources,列出分配的资源。

用来描述这些资源的结构是CM_PARTIAL_RESOURCE_LIST类型,它包括一个CM_PARTIAL_RESOURCE_DESCRIPTOR结构的计数数组。

数组中每一个资源描述符都有一个Type成员[3],它表示所代表的资源的类型。主要有4个重要的共同体类型是Port(端口)、Interrupt(中断)、Memory(内存)、Dma(直接内存访问)。得到了设备的I/O地址,就可以对设备进行读取了,在读写端口地址和内存时应该使用标准的内核读取例程,在WDM中应使用HAL宏等。这样就可以不用考虑不同操作平台的特性,也可以更好的适应Windows 2000多任务,多进程环境的要求。

在分配硬件资源时,首先必须编辑安装文件(inf文件),它包含了WDM设备驱动程序的制造商信息、要复制的文件列表、要创建的注册表项等。INF安装文件向操作系统添加了硬件资源。当驱动程序收到IRP_MJ_PNP的IRP_MN_START_DEVICE的子码时,驱动程序获得设备的硬件资源。

3 动态链接库(.dll)

虽然驱动程序是为设备硬件层编程服务的,但同样需要和应用程序进行通信,从而最终达到应用程序控制设备的目的。

通常情况下,应用程序通过专用的API函数操作硬件,但由于这些函数携带参数很多,使用起来并不方便,因此可以另外开发一套用于中转数据的功能函数集(动态链接库),可以使得底层驱动设备对用户是透明的[2]。采用这种分层结构,应用程序通过动态链接库(.dll)来存取I/O设备。动态链接库(.dll)提供给应用程序最常用的接口函数,包括设备初始化,关闭设备,存取端口等。在应用程序中加入特定的动态链接库可以很方便的操作端口,并且可以重复使用,缩短了开发周期。

4 结束语

WDM驱动程序模型具有较好的可移植性:编写驱动程序时,WDM规定只使用ANSI C标准规定的语言元素;硬件和软件的可配置性灵活:使用HAL工具调用低级总线驱动程序或实现一个标准控制接口,避免直接引用硬件;使用注册表作为配置信息的容器;可运行在多处理器平台上。基于WDM驱动模型设计的驱动程序可以稳定地在Windows 2000/XP/NT下运行,可以更好的实现分布式的数据监测和控制。

参考文献

[1]武安河.WDM设备驱动程序开发[M].北京:电子工业出版社,2003.

[2]Cant C.Writing Windows WDM Device Drivers[M].孙义,译.北京:机械工业出版社,2007.

[3]李建.Windows2000下I/O设备驱动程序设计[D].北京:北方交通大学,2003.

[4]张帆.Windows驱动开发技术详解[M].北京:电子工业出版社,2008.

[5]汤冬谊.Windows NT4.0下设备驱动程序的开发与应用[J].电子技术应用,2000(9).

I/O驱动 篇2

带有I/O模块和处理器的导轨被称为本地I/O导轨;带有I/O模块、电源、远程I/O通信卡并且安装在远离本地I/O导轨的导轨被称为远程I/O导轨。远程I/O导轨的`数目取决于不同处理器能够控制变量的数目。

远程I/O导轨与处理器之间的通信可以采用多种方式实现,具体包括同轴电缆、双轴电缆、屏蔽双绞线等,如果距离较远而需要考虑抑制噪声干扰问题可以采用光纤通信。

并行I/O模块:

并行I/O模块承担了与外部系统进行信息和数据交互的重要责任,可以用于扩展外围器件,者直接动键盘、LED等简单外部设备。

通常来说,51单片机有4个8位的并行I/O口,分别为P0、PI、P2、P3四组,其中PO和P2既可以用作普通I/O端口也可以当成数据地址端口,P3则在作为普通I/O端口的同时还具有其他(第二)功能,只有PI仅仪用作普通I/O口。

I/O驱动 篇3

随着嵌入式系统的发展,多功能IO采集卡在工业控制中得到广泛应用,实时、有效和高速地完成控制信号到嵌入式处理器处理的信号交互传递成为工业控制系统的重要环节,而IO卡驱动编写质量的好坏是其中的关键。本文以基于PENTIUM电脑在VxWorks下开发多功能IO采集卡驱动,详细介绍了基于VxWorks下多功能IO卡驱动的设计和实现过程。

2 多功能I/O卡简介

本文采用的多功能IO采集卡采用PCI总线,具有32路光隔离开关量共阴输入、32路光隔离开关量共阴输出、3路光隔离计数输入。PCI总线的桥芯片为9052芯片。PCI9052是PLX技术公司继PCI9050之后推出的低成本、低功耗、高性能总线接口芯片,通过该芯片可以使多种局部总线快速转换到PCI总线上。

3 PCI配置空间

PCI是Intel公司于1991年提出的新的总线标准。每个PCI设备有3种物理空间:配置空间、存储器空间和I/O空间。配置空间是长度256字节的一段连续空间(16个32位寄存器)其中前64个字节为头标,其余192字节为设备相关信息。在64字节的头标中,前16字节的定义是确定的,后48字节的具体含义因设备而异。配置空间头标区如图2所示。配置空间中的一个重要部分是基地址寄存器(Base Addresss Register),它的内容是PCI设备的地址空间映射到系统地址空间的起始物理地址。其中,bit0=1表示IO空间映射,bit0=0表示存储器空间映射。所有PCI设备必须实现存储器空间映射。通过向BAR写全1即可确定所需地址空间的大小[1]。

要访问某一PCI设备的配置空间需要给出总线号,设备号、功能号和寄存器号。要对PCI设备各种功能进行操作一般通过I/O空间和存储存器空间,具体和PCI设备硬件相关。获得空间的基地址后,就可根据PCI设备说明书进行功能驱动编程。

4 VxWorks的多任务支持与PCI总线支持

VxWorks是由Wind River公司开发的一种强实时性嵌入式操作系统。支持80x86、Motorola PowerPC、ARM等多种嵌入式CPU。它开放的体系结构和对工业标准的支持是得在多厂商平台上设计实时系统变得容易,而且在不同处理器之间移植代价极小。VxWorks操作系统具有高度的可裁剪的微内核结构、高效的多任务调度、灵活的任务间通讯手段、快速准确的I/O系统等优点。

4.1 Vx Works多任务支持

任务是代码运行的一个映象,VxWorks内核使任务能快速共享系统的绝大部分资源,同时有独立的上下文来控制个别线程的执行。VxWorks内核采用基于优先级的抢占式调度法作为它的缺省策略,同时也提供了轮转调度法。基于优先级的抢占式调度方法为每个任务指定不同的优先级。没有处于悬置或休眠态的最高优先级任务将一直运行下去。当更高优先级的任务由就绪态进入运行时,系统内核立即保存当前任务的上下文,切换到更高优先级的任务[2]。

4.2 VxWorks的PCI总线支持

V x W o r k s中驱动硬件的工作是由B S P来完成的。BSP中的驱动程序管理特定目标环境中的设备,对其进行控制和初始化。所谓板级支持包BSP(board support packet)通常是指针对具体的硬件平台,用户所编写的启动代码和部分设备驱动程序的集合。在VxWorks操作系统中,BSP是介于底层硬件环境和VxWorks之间的一个软件接口,它的主要功能是系统加电后初始化目标机硬件、初始化操作系统及提供部分硬件的驱动程序。PCI设备驱动是其中重要的一部分。

5 多功能IO采集卡PCI驱动设计与实现

5.1 VxWorks下多功能IO采集卡设备查找和物理空间的获取

在实际工作中首先通过多功能I O采集卡厂商I D(0x10b5),设备ID(0x5201)号,利用VxWorks内部函数pci Find Device()获得设备实例、总线编号、设备编号和功能编号;然后调用pciConfigInLong()获得多功能IO采集卡设备的配置空间、内存空间、I/O空间的地址;利用pci Config In Byte得到设备中断号;在利用sysMmuMapAdd()函数建立PCI的内存映像[3]。代码如下:

通过调用pciIntConnect()将中断服务程序与中断向量连接起来,然后打开中断,并挂接好中断服务函数使能够响应中断。注意此时中断号要利用INUM_TO_IVEC转换为中断向量才可使用[4]。中断服务函数如下:

5.2 程序流程图如图下

6 结束语

本文介绍了VxWorks下多功能IO采集卡设备驱动程序的详细编写,介绍了PCI总线下PCI9052芯片驱动的开发,只需少量改动就可应用到其它平台。通过对驱动程序的编写,作者深刻体会到了VxWorks下PCI总线设备的查找策略与方法。

参考文献

[1]张豫榕,董磊.VxWorks的PCI配置方法和应用实例[J].电脑编程技与维护,2005,(1):81-85.

[2]VxWorks Programmer’s Guide5.4[z],U.S.A:,Wind River Systems,Inc,1999.

[3]任秀丽.VxWorks操作系统中对PCI总线驱动程序的设计与实现[J].锦州师范学院学报(自然科学版),2001,(9).

关于I/O模拟的讨论 篇4

多年以来,Windows都为这种机制而引以为豪,其实在Windows下,有这样的一个原则,硬件例如CPU最好是一直工作的,这样才能得到更加充分的利用,而在Windows下,程序都是以进程形式获得在CPU这类的硬件中执行的机会,而作为轻量级的进程,执行资源的实际获得者线程的角度上看,就是要让线程不要停下来,需要让各个线程就它们正在执行的操作进行相互的通信,Microsoft在这个领域进行了数十年的研究和测试,终于开发了这种机制,叫做I/O完成端口(I/O completion port),通过这种机制,就可以让线程在读取设备或写入设备的时候不必挂起等待设备的响应,从而很大程度上提高了吞吐量,实现了计算机性能的巨大提升,如图1所示。

首先分析一下Windows的消息机制,只有了解了Windows的消息机制才能明白,什么是消息,Windows下利用上述的I/O机制,实现了线程与I/O之间的交互不必需要线程的挂起,但是消息产生到接收又是怎么解决的呢?Windows感知到有I/O的操作以后,会将该消息进行封装成为struct tagMSG(详细内容请查阅MSDN),这个结构体中将包含消息的类型,参数,时间,位置,和传递的对象。Windows将该消息投入到Windows消息队列,然后等待应用程序从队列中提取相对应的消息,在这里要明确几个问题,便是模拟I/O的层次问题和模拟的关键是什么?正如图1表达的,模拟可以在驱动级,系统级,或者用户级3个级别上进行,关键就在于模拟的何种消息、何时、何位置、发送给那些应用程序,这就成为了I/O模拟的关键所在。

2 用户级I/O模拟

正如图1所示,从消息队列到指定应用程序的这一段路径上的I/O模拟,便是用户级模拟,用户级模拟的特点是:

(1)通过Windows消息机制,并由系统发出,给指定的应用程序。

(2)指定的应用程序通过自己的窗口句柄等标识,从消息队列中获取消息。

这一部分的模拟需要用到Windows API,首先了解到在Windows下的应用程序,都会拥有一个自己的窗口句柄,这如同一个ID一样,指向了某一个窗口程序,就通过获取到指定应用程序的句柄,然后发送特定消息,这如何来实现呢,分享一段模拟代码:

这里就不再赘述一些细节了,但是需要注意的是,在FindWindowsEx中的第二参数,解决一些存在父子窗口的情况,通过对子窗口的句柄,有点类似线程ID了,就可以向指定线程发送消息,按键的消息需要延迟200毫秒,这是因为正常人的点击操作便是200毫秒,这样首先可以避免写入消息队列过快,造成溢出,也可以满足一些需要一定按键时长程序的特殊要求。这里的PostMessage函数有时可以用SendMessage函数替代,本身参数上没有区别,但是核心在于如果使用的是PostMessage那么发出消息后,模拟程序是不会理会该消息的处理的,但是使用SendMessage的话,应用程序就会一直等待该消息被正确处理的反馈,这样会一定程度上影响模拟程序的正常运行,因此建议使用PostMessage函数。其次Windows的消息叫做Windows_Message,这类消息共有1024(0x0400),所以可以设置高于1024的自定义消息。这样就可以模拟很多Windows下无法模拟的I/O消息,但是弊端就是要为自定义消息编写处理函数。

3 系统级I/O模拟

这一部分分析操作系统到消息队列这一段路径上的I/O模拟,这一段的模拟所具有的特点是:

(1)系统并不指定发送的对象,接受消息的进程为当前的活动进程。

(2)接收消息的程序可以发生改变,换句话说是可以存在进程间切换的。

首先分析一下正常情况下键盘消息的产生过程,这好比要完成对某一好友的问候,那么应当先选中一个好友,然后对他发送你好的消息,这一过程就是平时使用鼠标点击选中当前活动进程,或是用键盘切换选择活动进程的过程。这一部分的模拟通过Windows API也是可以实现的,下面我们分享一段模拟代码:

键盘消息的模拟,需要讨论的是虚键码MapVirtualKey函数,这个函数把逻辑上的‘U’键转换成计算机可以识别的二进制虚键码,可以不使用这个函数,但是效果就是模拟出的键盘消息不会被一些DirectX类游戏所接受,鼠标事件的模拟就要显得相对复杂了,因为不仅要产生事件消息,还要产生位置消息,这里的案例是对640*480窗口向全屏的鼠标坐标转换,有点类似窗口压缩的意思,需要解释的是对于一些DirectX类的射击游戏的鼠标模拟,这套方案并不是首选方案,其原因会在下面的驱动级模拟中详细给大家分析。

4 驱动级I/O模拟

这一部分要分析从驱动到操作系统和一种特殊的消息传递方式,在这之前,先要了解这样一个事实,在应用程序中有一类游戏应用程序叫做DirectX类游戏,比如冰封王座,CS,街霸,铁拳等,这类游戏的一个共同特征是:

(1)需要很高的即时操作要求,而且操作频繁。

(2)不使用Windows的消息机制,而是与驱动直接交互。

首先为了很好的人机交互感,这类游戏都会将操作精确到毫秒级,而且会产生大量的操作,这就要求对I/O缓存的一定使用要求,其次为了实现这类游戏的即时要求,这类游戏都会选择绕过Windows消息机制,因为通过Windows消息机制至少都有数百毫秒的延时,这难以满足游戏的需要,为此目的,这类游戏会选择直接与驱动进行交互,来接受I/O的操作。在这个层面的模拟就会显得比较复杂,而且Windows的API就不太好用了。

因此在这个层面的I/O模拟有两种设计方案,一种是需要重写某些I/O设备的驱动,这是比较麻烦的,还有一种方法是将消息写入某个特定的驱动然后产生相应的消息,下面着重分享一下第二种方法,写入驱动程序:

使用写入驱动的接口是WinI/O提供的,通过WinI/O就可以和驱动进行一定程度上的交互,分析一下这几段关键性代码:首先KBCWait4IBE()函数是用来检测驱动的缓存是否为空的,因为开始讨论到,如果模拟的消息过平凡地投递到驱动,那么消息就会出现一定程度上的溢出,这样的话,很多的操作就会出现丢失,这样是很不好的,所以每当要将内容写入到驱动的时候,都要检测一下是否驱动的缓存已经满了,这并不会造成严重的延迟,但是对一些组合操作来讲,丢失一个操作就有可能丢失了一批操作,所以在驱动级模拟I/O的操作关键就在于避免缓存溢出。此外,MY_KEY_DOWN&MY_KEY_UP是相类似的,将差异分析一下,首先,要产生的按键的ASCII码转换为虚键码,然后等待缓存,当可以写入的时候首先要发送一个命令消息0xD2,即为写入缓存,然后得到写入的权限后写入一个数据0xE2,告诉驱动要写入的是一个键盘消息,然后等待缓存,写入要写入消息的虚键码,于是消息被写入,但是这个时候键盘消息是按下消息,如何将其按起呢?使用0x80也就是标识当前某一按键被取消的标识位,当这一位被标识后,按键消息就变成了按键取消消息,从而从键盘上驱动模拟发出这一消息。

5 结语

详细介绍了在用户级、系统级和驱动级实现对I/O设备的模拟操作,分享了Windows API编程、WinIO驱动编程的案例。也详细地分析了Windows消息机制的优缺之处和如何利用和脱离Windows消息机制。

摘要:详细分析Windows的I/O机制,提出了分别在用户级、系统级、驱动级的I/O模拟操作,通过实际案例和源代码分享在I/O模拟上的得失,着重介绍鼠标与键盘的模拟。

关键词:I/O机制,I/O模拟

参考文献

对象I/O技术的模拟实现 篇5

我们知道C++对象是“存活”在RAM中的,由于RAM的易失性[1],程序需要将对象存入磁盘中,将来需要时再把对象读入内存加以恢复,这样一来就好像对象一直“活”着一样,因此对象的持久化是C++中的一个非常重要的操作。

许多程序员可能有这样的误区,利用下面的代码:saveClassName();className=readClassName();p=new className;不就轻松实现对象的保存和恢复了吗?

需要指出的是,在C++中,是通过new A而非new“A”(或className=“A”,new className)实例化A的对象。换句话说,试图利用下面的代码className=readClassName();p=new className;来达到通过类的字符串名称动态创建对象的做法是根本行不通的,因为p=new className根本无法通过编译![2]

由此我们得出对象的持久化需要的两个条件:

(1)获取对象所属类的名称的能力;

(2)能根据类的字符串名字动态创建对象的能力。

这两种能力的获得目前有两种解决方案:

一是由C++编译器(compiler)提供———例如Borland C++4.5:

二是由程序员自己加上去。

本文是通过第二种方法模拟实现对象的持久化机制,从而深入探讨了对象I/O技术的实现机制。

本文结构如下,首先描述了对象持久化的实现,其次对实现进行了验证,最后是论文进行总结。

1 对象持久化的实现

为了说明问题而又不失一般性,我们假定有三个类,分别是Object,A和B,其中A和B都派生于Object,类的定义如下:

为了让对象具备持久化的两个条件,需要依次为对象添加如下信息。

1.1 为每个类增加对象创建函数CreatObject,如表2所示。

1.2 增加类的识别信息(类名称或ID等)以及继承信息,由于这部分信息比较多,可以将其整合到一个结构体Struct ClassInfo中。ClassInfo中保存有两个链表:

类的继承链表和程序中所有类的类型信息链表。类的识别能力就由这两个链表来完成。换句话说,我们希望在main函数执行之前内存中就存在如图1所示的两个链表。其中类的继承链表是由Struct ClassInfo的带参构造函数完成的(在VC++中,结构体也可以有构造函数),而类的类型信息链表则是由ClassInfoInit类完成的。Struct ClassInfo和ClassInfoInit的定义如表3所示。注意,链表的创建是在它们的构造函数中完成的。

最后一步,将类型信息作为类的静态的成员变量添加进来,并为每个类实例化静态的初始化类,目的是在main函数执行之前得到图1所示的两个链表。

在这要强调一下static关键字的作用:

(1)如果类的成员变量被Static关键字所修饰,则这该属性不是为类中的每个对象分别拥有,而是共用,其引用形式不是对象成员变量,而是类成员变量,即不需要市里实例化对象就可以使用。成员函数也与此相仿[3]。

(2)如果对象(包括作为类成员的对象),如initObject、ObjectInfo等,被说明为Static,则这些对象是在main函数执行之前就已经存在了,换句话说,这些对象的构造函数是在main函数调用之前就已经被调用了。因此在main函数执行之前,内存中就已经存在着图1所示的链表就可以理解了。

我们添加的RTTI信息能否有效的支持对象的持久化可以由试验来验证。

2 试验

该试验主要验证了对象持久化必须具备的两个能力,即动态创建对象能力和获取对象所属类的能力。试验的环境如下:操作系统Windows XP sp2,IDE环境是VC++6.0 SP6。如需要全部源代码可与作者联系(hehh6@henu.edu.cn)。

通过对象增加的RTTI信息(增加的静态成员变量),获取对象所属类的能力自然具备。

动态创建对象能力实际上就是根据类的字符串名称来实例化对象的能力,在图1所示链表的支持下,该功能可以非常轻松的实现。

思路如下:通过ClassInfo::pFirstClass查找类名匹配的ClassInfo,利用ClassInfo中的pCreateObject指针实例化对象,为方便起见,可为程序增加查找函数

3 结束语

本文在手动添加的RTTI信息的支持下实现了对象的持久化,从中读者可以深入了解对象持久化的的实现机制。

在商业的编译器VC++中其实现持久化是通过一个神秘的宏,当将该宏展开后,VC++实现持久化的的思路和本文大同小异,只是更精巧[4]。

参考文献

[1]Stanley B.Lippman.Inside The C++Object Model(深度探索C++对象模型)[M].侯捷,译.武汉:华中科技大学出版社,2001.

[2]葛磊.The Object's Permanence Technology and Its Realization in MFC[J].开封大学学报,2006,20(1).

[3]钱能.C++程序设计教程[M].第二版.北京:清华大学出版社,2005:418-419.

远程I/O系统在罐区的应用 篇6

关键词:远程I/O,通信,DCS

0 引言

金陵石化芳烃部中间罐区仪表采用远程RTU接入DCS方式, 现场检测、报警仪表的信号接入远程I/O单元, 由远程I/O单元转换成通信信号, 连接至相应的DCS系统, 控制仪表及可燃气有毒气检测仪表采用电缆直连至相应的DCS系统。

现场每套远程I/O系统输出两路Modbus信号, 分别进入两个不同装置的DCS系统, 一路进PX装置, 另一路进3重整装置。

1 远程I/O系统

模块化的远程I/O系统通过总线接口将现场二进制和模拟量的传感器和执行器连接至控制系统, 传输安全区域或者爆炸危险区域的现场过程数据。远程I/O系统可连接设备:流量变送器、阀门定位器、压力传感器或者温度变送器、热电偶 (TCs) 、电阻式温度检测器 (RTDs) 、机械触点以及声光报警器等。远程I/O系统兼容Profibus-DP、Modbus-RTU、Modbus TCP/IP和Foundation Fieldbus等网络协议。远程I/O适用于爆炸危险区或者严酷工业环境, 例如海洋平台和户外。典型的应用行业包括石油天然气 (内陆及海洋) 、制药、化工、污水处理、食品饮料等。

远程I/O系统具备高适应性和操作简单的特征。系统安装在现场设备侧, 仅需一根总线电缆即可连接远程I/O系统到DCS, 能够减少接线, 还能够节省时间、节约成本和减少工作量。

P+F公司的LB系列远程I/O具备危险区2区认证, 可安装在Zone 2、Class I、Div.2或者非危险区域。该模块化的信号调节系统将现场信号关联至非危险区域的控制系统, 连接方式有安全区域现场连接 (NonEx) 和本质安全区域现场连接 (Ex i) 。

金陵石化公司芳烃部新建中间罐区正是采用LB系列的远程I/O系统, 如图1所示。

该系统的底板结构如图2所示。X4为现场总线接口, 用来与DCS通信, 现场实际用于与PX通信;X5为冗余现场总线接口, 用来与DCS通信, 现场实际用于与#3重整通信;X6为服务总线, 用于连接PC机进行相应的组态;X7为扩展机架接口;CHANNEL1/2为通信模块;CHANNEL3-24为I/O卡件;POWER1-3插槽为插相应的供电模块。

2 远程I/O系统的组态过程

(1) 打开PACTWARE, 添加设备, 如图3所示。

(2) 选择添加相应的LB系统, 选择好相应的COM口后选择SCAN SERVICE BUS, 自动扫描网关设备, 如图4所示。

(3) 按照设计图纸在每个通道插入相应的插件, 然后进行具体的点组态, 如图5所示。

(4) 在实际的组态中, 为了通信方便, 处理量程统一设置成0~4095。为了能够与TPS系统通信, 必须对相应的Modbus地址进行分配, 如图6所示。点击Auto marshalling按钮, 系统会自动根据卡件的通道号分配相应的地址。组态结束后, 对相应的系统进行下载。

3 与DCS通信

LB远程I/O系统与Honeywell TPS系统采用的是标准的Modbus-RTU通信协议。

控制器和主机为主从关系。仅一设备 (主设备) 能初始化传输 (查询) , 其它设备 (从设备) 根据主设备查询提供的数据做出相应反应。这种传输方式也使得信号在Modbus网络中的通信井然有序。

根据系统的特点, 采用RS-485接口, 接口采用平衡驱动器和差分接收器的组合, 使用屏蔽双绞线传输 (一般只需二根连线) 数据, 抗共模干扰能力增强, 抗噪声干扰性好。

将现场远程I/O系统的通信线连接DCS中的SI卡FTA板, 在DCS中组态相应的ARRAY点, 设置地址、波特率、通信协议, 分别如图7、图8、图9所示。

建立相应的通信之后, 要对模拟量点的量程进行转换, 以达到实际使用要求。

4 结语

远程I/O系统不但节省成本, 减少工作量, 而且可以在线对参数进行修改, 在线监测功能强大, 利于故障的判断, 减少了维护量。

参考文献

[1]丁宝苍.过程控制系统与装置[M].重庆:重庆大学出版社, 2013

[2]乐嘉谦.仪表工手册[M].北京:化学工业出版社, 2003

[3]厉玉鸣.化工仪表及自动化[M].北京:化学工业出版社, 2011

[4]张春华, 肖体兵, 李迪.工程测试技术基础[M].北京:机械工业出版社, 2011

[5]王树青, 乐嘉谦.自动化与仪表工程师手册[M].北京:化学工业出版社, 2010

[6]武平丽, 高国光.过程控制工程实施[M].北京:电子工业出版社, 2011

CC2530普通I/O口的扩展 篇7

1 CC2530的I/O口扩展方法的总体思路及各组成工作原理

1.1 CC2530的I/O口扩展方法的总体思路

本扩展方法采用CC2530的I/O口模拟IIC总线的SCL和SDA, 通过IIC总线控制PCA9554芯片, 使串行通信变成并行通信。从理论上来讲CC2530芯片P1口的8个I/O口就可以连接4组IIC通信, 每组因扩展芯片地址A2A1A0的不同可同时支持8个芯片, 每个芯片又可控制8个端口。因此, CC2530的P1口从理论上就可支持128个 (4×8×8) 端口, 如图1所示。并且, 如果芯片固定的头地址不一样的话, 例如PCA9554和PCA9554A, 那么端口数量又可增加一倍, 这样P1口就扩展成了256个端。依此类推CC2530的I/O口通过扩展数量呈几十倍的增加, 可大大丰富I/O口的应用。

1.2 IIC总线工作原理

IIC总线只有两条线, 一条是数据线SDA, 另一条是时钟线SCL。数据线SDA在时钟线SCL的控制下可串行发送和接收数据, 传送速率最高达100kbps。各被控制器件均并联在这两条线上, 每个接到IIC总线上的器件都有唯一的地址, 通过不同地址决定通信对象, 如图1所示。这样, 各控制电路虽然挂在同一条总线上, 却彼此独立, 互不相关。IIC总线的优点是占用的空间非常小, 可避免线路互连而使电路板走线错综复杂的现象, 减少了电路板上的布线空间, 降低了互联成本。

IIC总线上只有四种信号:开始信号、停止信号、重新开始信号和应答信号。IIC总线上能实现主/从双向通讯, 器件发送数据到总线上, 则定义为发送器, 器件接收数据则定义为接收器。主器件和从器件都可以工作于接收和发送状态。IIC总线时序如图2所示。

1.3 PCA9554工作原理

PCA9554是带中断的GPIO扩展芯片, 它提供了IIC总线方式应用中的8位串行转并行输入/输出口的扩展。PCA9554共有4条命令, 在总线主控制器 (本文中为CC2530) 向PCA9554发送写数据过程中, 命令字节是紧跟地址字节, 之后第一个字节作为一个指针指向要进行写或读操作的寄存器。CC2530通过总线写I/O口的相应配置位来激活端口的输入或输出。通过给PCA9554的A2A1A03个管脚不同的电平来实现不同IIC地址, A2A1A03个管脚可组成8个地址码, 由此总线上最多允许挂8个PCA9554。而PCA9554与PCA9554A的IIC固定地址不同 (PCA9554的固定地址为01000A2A1A0, PCA9554的固定地址为01110A2A1A0) , 这样就允许16个器件 (PCA9554和PCA9554A各8个) 连接到同一个IIC总线上, 每个器件扩展出8个I/O端口, 这样CC2530的两个I/O端口就可扩展到8x16个I/O口。

2 扩展I/O口的应用

本应用通过CC2530的I/O口 (P1.0和P1.1) 模拟IIC总线的SCL和SDA, 然后通过IIC总线形式控制GPIO扩展芯片PCA9554, 最后通过扩展的IO来控制LED、蜂鸣器、按键信号、继电器等, 如图3、4所示。

3 结语

本文通过IIC总线形式控制GPIO扩展芯片PCA9554扩展CC2530的I/O口。在文主要提出了具体的硬件设计, 并运用于实践中。CC2530的I/O口进行扩展, 使I/O口的数量大大增多, 能丰富开发设计者的运用。

参考文献

[1]施邦平.采用I2C器件扩展单片机的多级通信[J].自动化与仪器仪表, 自动化与仪器仪表, 2006 (6) :63-64.

I/O驱动 篇8

关键词:I/O性能,流,缓冲区,分配和回收

Java应用程序都会经常使用java.io包, 例如磁盘文件读写和通过网络传输数据。然而初学者由于对java.io包的理解的局限性导致编写的程序I/O性能很差。所幸的是, 只要对java.io包有了很好的理解, 就可以杜绝这方面的问题, 从而保证程序拥有较好的I/O性能。

本文首先对java.io包做一个简要的介绍, 然后指出导致I/O性能低下的根本原因是没有采用缓冲机制, 然后循序渐进地采取了三种策略, 将I/O性能逐步提高到168倍, 这三种策略分别是采用缓冲流, 定制自己的缓冲区, 定制静态的固定长度的缓冲区。

1 I/O操作的基本概念

在Java I/O中最基本的概念是流 (Stream) , 流是一个连续的字节序列, 包括输入流和输出流, 输入流用来读取这个序列, 而输出流则用来写这个序列, 在默认情况下Java的流操作是基于字节的, 即一次只读或只写一个字节。

java.io包提供了Input Stream和Output Stream作为对I/O操作的抽象, 这两个接口决定了类层次结构的基本格局。Input Stream和Output Stream的具体实现类提供了对不同数据源的访问, 如磁盘文件和网络连接。

java.io包还提供了过滤流 (Filter Stream) , 过滤流并不指向具体的数据源, 而是在其他流之上进行了包装, 这些过滤流其实是java.io包的核心。从性能的角度来看, 最重要的过滤流是缓冲流 (Buffered Stream) , 图1显示了一个简化的类层次结构图。

2 缓冲流

导致I/O性能低下的主要原因是没有对I/O操作进行缓冲。众所周知, 硬盘擅长于大块数据的读写, 但是在小量数据的读写上性能不好, 所以, 为了最大化I/O性能, 我们应该选择批量的数据操作, 而缓冲流正是为这个目的设计的。缓冲流, 包括Buffered Input Stream和Buffered Output Stream, 它为I/O流增加了内存缓冲区, 使得Java程序一次可以向底层设备写入或者读取大量数据, 从而提高了程序的性能。

为了更好地理解缓冲流的效果, 请阅读程序清单一, 这个例子采用了原始的文件流实现文件的拷贝。copy方法打开了一个File Input Stream和一个File Output Stream, 并将数据从一个流直接拷贝到另一个流。由于read和write方法是基于字节的, 所以实际的磁盘读写也是按字节发生的。实践证明使用这段代码拷贝一个8M的文本文件需要花费36750ms。

程序清单一中的copy方法只需稍作修改就能有效地改善性能, 如程序清单二所示, 它在原始的文件流之上采用了缓冲流Buffered Input Stream和Buffered Output Stream, 缓冲流将每一个小的读写请求积攒起来, 然后一次性地批处理, 通常是将几千个读写请求合并成一个大的请求。改进后的copy方法拷贝一个8M的文本文件需要花费1187ms, 性能大约提高了31倍。

3 建立自己的缓冲

缓冲流虽然在它的内部增加了内存缓冲区, 使得在缓冲区和底层设备之间写入或读取大量数据成为可能[2,3], 但是在这之上Java程序仍旧使用while循环从该流 (实际上是缓冲数组) 按字节读写数据。由于缓冲数组的大小是一定的, JVM需要针对数组做越界检查, 该操作会导致额外的系统开销。另一方面, 为了支持多线程环境, 将数据从Buffered Input Stream的缓冲数组拷贝到Buffered Output Stream的缓冲数组, 其中的方法调用很多都是synchronized, 这也会导致额外的系统开销。所以尽管程序清单二所示代码可以有效地改善性能, 但是改善的程度仍然不尽人意。

还是利用硬盘擅长读写大块数据这一特性, 我们可以自己建立缓冲, 以避免上述额外的系统开销。这需要使用Input Stream和Output Stream提供的两个重载方法, 它们允许按字节读写, 也可以按字节数组读写, 如下所示:

程序清单三创建了自己的缓冲区, 即字节数组byte[]buffer, 其大小是整个文件的字节长度, 然后将整个文件一次性读入内存, 再一次性写到另一个文件。这个代码非常快, 拷贝一个8M的文本文件所花费时间降低到750ms。

注意, 使用这个策略需要权衡两个因素。首先是缓冲区的大小, 它所创建的缓冲区的大小等于被拷贝的文件大小, 当文件很大时, 该缓冲区也会很大。第二, 它为每次文件拷贝操作都要创建一个新的缓冲区, 当有大量文件需要拷贝时, JVM不得不分配和回收这些大缓冲区内存, 这对程序性能是极大的伤害。

如何在保持速度甚至速度更快的前提下避免这两个缺陷呢?方法是这样的:创建一个静态的固定长度的字节数组, 如1024*1024字节即1M, 每次只读写1M的数据。虽然对于大于1M的文件会需要多次读写才能完成整个文件的拷贝, 但是这样避免了内存的反复分配和回收。缓冲区大小是可以调整的, 针对某个具体的应用场景, 我们可以在速度和内存之间取得一个最佳的平衡。

程序清单四的copy方法使用了这样的1M字节的数组, 这个版本表现更为出色, 它拷贝一个8M的文本文件所花费时间只有218ms, 性能提高了168倍。

值得注意的是代码中的同步块, 在单线程环境下没有同步块是可以的, 但是在多线程环境下需要同步块防止多个线程同时对缓冲区实施写操作。尽管同步会带来系统开销, 但是由于while循环的次数很小 (8M文件只要循环8次) , 所以由此带来的性能损失是可以忽略不计的。实验证明, 有同步块的版本和去掉同步块的版本, 性能是一样的。

下表显示了采取四种不同的策略拷贝一个8M文件所花费的时间。它充分说明, 有效地改进缓冲机制可以大大提高程序的I/O性能。

4 结束语

一般情况下, 我们总可以为具体的应用程序找到改善I/O性能的方法, 这需要具体分析该应用程序的目的和操作特性。例如, 考虑FTP和Http服务器, 这些服务器的主要工作就是将文件从磁盘拷贝到网络的Socket, 一个网站的主页通常比其他网页访问得更多。为了提高性能, 我们可以建立快速缓冲贮存区, 将那些经常被访问的文件做缓存, 这样这些文件就不必每次从磁盘读写, 而是直接从内存拷贝到网络。

参考文献

[1]What is Java I/O?[EB/OL], http://www.roseindia.net/java/example/java/io/Java_io.shtml

[2]Buffered Input Stream, JavaTM Platform Standard Ed.7[EB/OL], http://docs.oracle.com/javase/7/docs/api/java/io/Buffered Input Stream.html

上一篇:《水浒传》的忠义观下一篇:桥梁工程造价