技术开发 频道

SaaS获得iPhone意外助力

    1. WinDriver简介

    目前大部分桌面操作系统基本都是WinNt核心的操作系统,并且Win98已经基本退出使用。而在WinNt操作系统下,应用程序一般都是运行在Ring3级别上,是不允许直接访问IO空间的,为此微软提供了DDK驱动开发包。第三方的公司也提供了DDK封装后的开发包方便用户使用,比如:WinDriver,DriverStudio等。

    WinDriver主要特性如下: 

    •不需要Kernel编程和调试。 
    •不需要专门的操作系统和驱动程序方面的知识。 
    •功能强大的向导,帮助您进行硬件诊断和自动生成代码。 
    •"Kernel插入" ,在内核级运行临界部分的代码来获取非常好的性能。 
    •支持I/O,中断控制和访问板卡映射的存储器。 
    •支持DMA,即插即用和多板处理。 
    •支持C、 C++、VB、Delphi。 
    •同样的代码能运行于Windows 9X/NT/2000/CE、Solaris、Linux、VxWorks等。 
    •动态装载驱动程序。 
    •增强支持主要的PCI芯片和IP厂商-PLX,Altera,AMCC,Galileo,V3,PLDA及其它。 
    •WinDriver调试监视器 - 当您的驱动程序正在运行时,您能监视内核模式的行为。

    2.LabWindows简介 

    LabWindows/CVI是National Instruments公司推出的一套面向测控领域的软件开发平台。它以ANSI C为核心,将功能强大,使用灵活的C语言平台与数据采集,分析和表达的测控专业工具有机地接和起来。它的集成化开发平台,交互式编程方法,丰富的控件和库函数大大增强了C语言的功能,为熟悉C语言的开发人员建立检测系统,自动测量环境,数据采集系统,过程监控系统等提供了一个理想的软件开发环境。由于LabWindows是一个标准的C语言开发平台,因此可以放心的使用其他任何语言编写的开发库函数,LabWindows提供的标准库函数或者用户基于它开发的库函数也可以被第三方的开发工具使用,当然这些开发库的使用还依赖LabWindows运行环境函数库和引擎。

    3.硬件设计 

    ISA总线数据采集卡基于ISA总线接口芯片开发,是一块标准ISA总线驱动电路板,主要由ISA总线接口电路、光电隔离电路、离散量信号输入电路、数据锁存器电路、继电器驱动电路和继电器等组成。 

    离散量信号输入电路(DI)由光电隔离与电平转换电路、输入缓冲器组成,完成四十九路离散量信号的输入。ISA总线如下图所示:

    LAD〔7:0〕是8位的数据总线。LA〔9:0〕是ISA的地址总线,I/O地址空间0100H~03FFH。ISA总线规定系统ISA设备最高位A9为0,用户扩展ISA设备最高位A9必须为1。需要注意的是,并不是所有的地址线都要进行地址译码,这里要根据板卡上实际I/O口空间的大小选择译码地址线的数目,如果需要寻址的IO设备多,那么板号地址线就要减少。

    4.软件设计 

    WinDriver开发驱动程序一般分以下几个步骤:安装、选择硬件、测试硬件、生成驱动框架代码、编译及运行。 

    ISA板卡与PC机接口采用8位ISA总线结构,控制方式为I/O空间访问,与外部设备的连接采用62针D型插座。电路板的I/O基地址,采用8位DOP开关(U5)设置。出厂时设置为0X200H。

    打开WinDriver软件新建一个工程,选择ISA CARD设备,弹出定义设备资源窗口,如图所示,由于我们的板卡只访问IO空间,寻址空间为0-7,无内存、中断和寄存器。假设基地址为0x200,则定义IO范围为0x200~0x207。然后点击Next,然后选择需要WinDriver生成何种开发环境的框架代码。在这里我们选择微软的Microsoft Visual C++ 6.0,WinDriver自动生成一个Dll工程框架代码。用户只需要简单的在框架代码基础上稍微修改,即可生成自己需要的驱动接口,主要函数及其功能如下:

    •设置板卡基地址函数

extern "C" __declspec(dllexport) void __stdcall DO_SetAdd(WORD ADDR)

    用户在调用任何驱动函数前先调用此函数设置板卡的基地址,地址范围为:0100H~03FFH,需要跟板卡的实际拨码开关相一致,否则板卡不会被片选。 

    此函数声明表明导出函数采用__stdcall(pascal)调用方式,由调用者负责参数从右往左入栈,被调用者清理堆栈。函数命名方式为C标准的命名方式,用Depends.exe观察导出函数的名称实际上就是“DO_SetAdd”,这对于C++编译器中调用此接口函数的时候,声明函数原型特别重要,否则会导致连接函数错误,因为C++为了重载函数的需要,所有的函数编译后的函数名称都进行了修饰。

     •设备初始化函数

extern "C" __declspec(dllexport) int _stdcall DO_Device_Initialize(DO_HANDLE *hDO)

    用户调用此dll导出函数来初始化硬件资源,并返回一个指向设备的句柄,DO_HANDLE *hDO是一个双指针,在函数内部动态分配一个设备句柄对象,返回该设备句柄的指针给用户,传递给后面其它函数使用。此函数中仅仅是调用两个内部函数DO_RegisterWinDriver和DO_Open,来完成软件的注册、版本冲突检测,板卡资源的分配、注册等。

     •关闭设备

extern "C" __declspec(dllexport) void _stdcall DO_Close(DO_HANDLE hDO)

    调用此函数来关闭设备句柄,释放初始化的时候动态分配的设备资源。

     •获取最近一次操作失败的原因

extern "C" __declspec(dllexport) char * _stdcall DO_GetErrStr()

    如果调用任何函数时候发生错误,可以通过此函数获取错误的详细说明。

     •读取IO空间或者内存空间的内部函数

void DO_ReadWriteBlock(DO_HANDLE hDIDO, DO_ADDR addrSpace,
DWORD dwOffset, BOOL fRead, PVOID buf, DWORD dwBytes, DO_MODE mode)

    所有的对IO口线的读写或者内存的读写都是通过此内部函数来完成的。addrSpace表明需要使用空间,该空间可以是IO空间也可以是一个内存空间,在板卡初始化的时候就会注册这些空间,dwOffset表明基于该空间的偏移量,fRead表明是读还是写,buf需要传输的数据缓冲区地址,dwBytes需要传输的数据长度,DO_MODE表明一次是传输1Byte传输,2Byte传输还是4Byte。 

    基本驱动框架生成后,用户可以再此基础上添加自己的函数,来实现自己的特定功能,比如向IO通道写控制字或者读IO通道的数字开关量或者AD值。

•自定义写IO的函数

extern "C" __declspec(dllexport)
void _stdcall DO_WriteByte (DO_HANDLE hDO, DO_ADDR addrSpace, DWORD dwOffset, BYTE data)

    此函数向特定偏移地址写一个控制字,控制字根据实际控制输出信号来决定。
写完所有的用户代码后,编译工程会生成.dll、.lib文件,并定义好包含函数声明的头文件。 

    LabWindows/CVI是一个标准的C开发平台,调用驱动接口中的函数,可以包含其头文件,在编译条件中加入其.lib文件或者将其.lib库文件包含到工程中即可。由于LabWindows是一个标准的C编译器和开发平台,故extern "C"关键字可以省略,但是调用方式__stdcall不能省略,因为标准C的调用方式是基于C调用方式,入栈方式和堆栈平衡跟pascal(__stdcall)调用都不相同,如果不加可能导致程序崩溃。

    在使用驱动前必须先设置板卡基地址空间,先将所有的输出关闭。代码片断如下:


    5.结论 

    对于自制数据采集卡或者其它硬件设备的驱动程序都可以通过WinDriver生成驱动框架代码,然后根据自己的控制信号和硬件设计,很容易的写出特定功能的驱动程序代码,封装成标准的DLL文件就可以在任何开发平台下就像使用Windows Api那样使用,达到跟特定语言不相关,可以达到事倍功半的效果,特别适合面向项目的开发模式。

0
相关文章