1 引言
在BC3192测试程序的开发过程中,最复杂的是仪器驱动程序的开发。同 VXI总线间进行的每一步联系和操作,都少不了仪器驱动程序的帮助。
用LabWindows/CVI(以下简称Labwin)软件可以开发出仪器的驱动程序。这主要是因为Labwin具有一部分通用的仪器设备驱动库。有了它们,用户可以比较容易地开发出几个系列的总线兼容设备驱动程序。如RS?232仪器驱动系列、 GPIB仪器驱动系列、VXI总线系列驱动程序,还有一些典型的特定驱动程序的实例,如Fluke45DigitalMultimeter(VISAI/O)(Fluke45数字型万用表)、Hewlett Packard34401AMultimeter( VISA)(惠普34401A型万用表)等。
一个典型的驱动程序由4部分组成。
第一部分是主程序,主要是由*.lib,*.obj,*.dll或*.c文件组成。
第二部分是包含文件(*.h),包括函数功能的定义,常量的声明以及全局变量的声明。
第三部分是设备功能面板部分(*.fp),包括树状功能信息定义。
第四部分是由ASCII码构成的帮助文件(*.doc),它包括指导用户的详细驱动程序帮助。
2 仪器驱动程序的操作
对用户来说,驱动程序完成一种或多种仪器功能,整个驱动程序库由多组程序有选择地构成。在Labwin的编程环境中选取仪器菜单,再从菜单中选取一个设备。这时将从屏幕中弹出一个功能面板,功能面板显示仪器的一些交互控制。函数调用自动生成的功能也随之加入整个应用程序。即使不提供功能面板,也能以手工方式进行驱动函数的调用。总地来说,设备驱动程序包括用以执行高级设备相关任务的功能函数。当用户把功能函数包含到程序中后,即使不了解设备的编程协议,也可以控制一个仪器正常运转。对它们的应用,可以在很大程度上减轻编程人员的负担。它们可以在软件开发中形成模块化,并大大提高软件的易用性和可维护性。
3 LabWindows/CVI开发驱动程序的优势
Labwin中设备的驱动程序是比传统概念中的驱动程序更高一层的概念。他们免去了编程人员频繁地同I/O端口打交道。它是放入用户应用程序的一种高层的软件功能。它不仅完全适用于目前各种标准的仪器设备,而且可对一大批老的仪器设备提供支持。
所有的Labwin应用的驱动程序,传递时在可能的情况下都伴有源码,并且很多都有完整的帮助文件。它们都是在Labwin的标准开发环境下开发的,用户可以根据具体情况改造自己的程序,使它们更加强大并对自己的应用程序有更大的弹性。
开发仪器驱动程序包括外部接口模块和内部设计模块。
3.1 外部接口模块
外部接口模块如图1所示。
功能主体:设备驱动的代码部分
程序员交互接口:图形化的编程助手,把交互控件状态转化为代码
程序员编程接口:调用各种函数
子程序接口:调用其它软件模块
3.2 内部设计模块
内部设计模块如图2所示。
功能主体:设备驱动的代码部分。包括初始化(包括结构复位、自检等)、设置函数(用一个软件程序集来实现相应功能。各种设备都有特定的设置函数。)、动作/状态函数(动作函数使仪器开始和停止测试,状态函数可获得仪器操作当前和即将出现的状态。)、数据函数(向仪器发送和接收数据)、终结函数(终结同仪器间的连接并释放系统资源)、应用程序函数(高级面向测试和功能函数)。
4 仪器驱动程序的设计
4.1 设计原则
在设计之前,必须进行驱动程序结构的设计,因为如果驱动程序的结构比较明了,会使程序员设计应用程序时更有条理。
其次,一定要把设计的驱动程序基于一个已设计好的核心驱动程序(即Labwin自带的驱动程序库)、或者是由一个核心驱动程序演化出来的驱动程序。
最后,以一个明确的步骤来编写你的仪器驱动程序(将在后面介绍)。
4.2 设计步骤
(1)命名这个驱动程序。
(2)定义这个驱动程序的功能和类。
(3)建立一个驱动程序的功能树。在Labwin中的功能树都以*.fp模式存储,并在引用时以层次化形式出现,并且在各分支功能上加帮助信息。
(4)对于程序中的每个函数:
——对于函数的参数定义包括变量类型、变量范围、错误代码等相关信息;
——在功能面板上实现新功能的创建,包括对功能面板和其中各个控件的帮助信息;
——为执行功能函数写代码;
——检验代码执行效果。
(5)为最终的设备源程序创建包含文件,包括函数定义和常量声明。
4.3 两个辅助工具介绍
(1)功能树的编辑器
用图3所示的是功能树编辑器,可以灵活地添加和删除各种函数,可从各个分支进入具体的函数定义功能面板编辑器。
图4所示的功能面板编辑器,可以控件的形式描述诸如函数参数、返回值、参考说明等函数的相关信息。随着各种控件的加入,相应的源代码也被实时地翻译在面板下方的文本框中。
4.4 自定义的数据类型
控件的使用方法相当简单,只需补充常说的可移植性问题,这一点同数据的定义是分不开的。Labwin对于驱动程序开发有自己专门的一套数据类型,它们可以精确地定义参数的类型和大小,而且它们具有很好的可移植性。各种定义如表1所示。
表1各种定义
4.5 函数定义的方法
驱动程序函数调用的返回值也与众不同,VISA/IO(Labwin中的虚拟设备接口)定义了一种非常有用的调用设备函数时使用的宏,如表2所示。
表2函数的定义
因为沿用了在Pascal语言中调用在DLL程序驱动的习惯,当用户在Labwin的环境调用用户定义函数时,把宏_VI_FUNC(表示任何用户函数)翻译成_pascal,而使用外部编译器编译时,则把宏解释成_far_pascal_export。同样在Labwin中,_VI_FAR(表示用户函数中任何的数组参数和输出变量)被翻译成空,而用其它编译程序时,被翻译成_far。
如下面这个函数 :
ViStatus _VI_FUNC tek2430a_read_waveform (ViSession instrSession,
ViReal64 _VI_FAR wvfm[],
ViReal64 _VI_FAR * xin,
ViReal64 _VI_FAR * trig_off);
在 LabWindows/CVI环境时,表示为:
ViStatus _pascal tek2430a_read_waveform (ViSession instrSession,
ViReal64 wvfm[],
ViReal64 * xin,
ViReal64 * trig_off);
而在其它编译环境下,表示为:
ViStatus _far _pascal _export tek2430a_read_waveform (ViSession instrSession,
ViReal64 _far wvfm[],
ViReal64 _far * xin,
ViReal64 _far * trig_off);
5 在BC3192测试程序中的应用实例
VXI的设备驱动程序包括以下几个主要功能。首先是分配设备的地址指针,这需要定义动态链接库的代码段和数据段为可移动和可删除,因为要用基指针指向每一个I/O动作,所以代码段和数据段是不定的;其次是VXI总线寄存器的写入和读取动作,这些操作需要我们使用刚得到的设备地址指针;再次是向缓存中读取和写入信息。另外,还有初始化,以及系统固定延迟时间等一系列功能。
在BC3192的测试程序中,结合Labwin自带的VXI总线的设备驱动程序,编写了一个简单的VXI驱动程序。它存于程序的根目录中,有4个支持文件,分别是vxirw.c、vxirw.dll、vxirw.h以及vxirw.lib。在我们的程序中,由于考虑到工作的效率,决定使用在VisualC++1.5的编译环境下,编译vxirw.c和vxirw.h程序,生成vxirw.dll及vxirw.lib的高效方法。这是由于Labwin使用一种LCC内建解释器对程序进行解释,其效率远不如直接使用动态链接库方便。用VC编译器编译的动态链接文件,可以在Labwin的函数中方便地进行调用。而且其效率同VC自身的调用不相上下。
如下面代码所示,正是使用了刚才所表示的函数调用方法。
void FAR PASCAL __export __loadds ReadReg(UINT La, UINT Offset, UINT FAR * Data)
/* 这 是 用 于 读 取 总 线 寄 存 器 的 函 数 。 * /
{
/* * Data=(UINT)(* (pPointer+ La* 32+ Offset/2)); * /
/* get the address pointer * /
GetPointer(La); /* 调用La全局变量取得寄存器地址*
/* read register * /
* Data=(UINT)(* (pPointer+ Offset/2)); / *把寄存器中的值通过偏移地址取出* /
/* free the selector * /
FreeSelector(wSelector);/*释放在取寄存器的值时所用到的字选择临时变量。 * /
}
程序的调用要熟悉大量硬件的特性,不属于软件总体设计之列,在此不再介绍。
6 结论
LabWindows这种以C语言为中心的编程方式有其优势,所带的C语言的功能比较灵活,而又便于开发一些大型的工程。它的类库的功能又可以开放地进行扩充,使系统的功能得到进一步增强。相对地,新型编程方式只能在固定的自带环境中运行,而且在表达复杂关系时,流程图的联系方式有很大的局限性。所以,Labwindows的编程方式在一段时间内将仍然拥有其地位。而今后的发展很可能是把两种编程方法进行集成,使我们在建立流程图后可以生成大部分程序代码,而细微的地方又可以进行C语言的调整。这样,我们的编程人员将拥有更方便的编程工具。
1 引言
在BC3192测试程序的开发过程中,最复杂的是仪器驱动程序的开发。同 VXI总线间进行的每一步联系和操作,都少不了仪器驱动程序的帮助。
用LabWindows/CVI(以下简称Labwin)软件可以开发出仪器的驱动程序。这主要是因为Labwin具有一部分通用的仪器设备驱动库。有了它们,用户可以比较容易地开发出几个系列的总线兼容设备驱动程序。如RS?232仪器驱动系列、 GPIB仪器驱动系列、VXI总线系列驱动程序,还有一些典型的特定驱动程序的实例,如Fluke45DigitalMultimeter(VISAI/O)(Fluke45数字型万用表)、Hewlett Packard34401AMultimeter( VISA)(惠普34401A型万用表)等。
一个典型的驱动程序由4部分组成。
第一部分是主程序,主要是由*.lib,*.obj,*.dll或*.c文件组成。
第二部分是包含文件(*.h),包括函数功能的定义,常量的声明以及全局变量的声明。
第三部分是设备功能面板部分(*.fp),包括树状功能信息定义。
第四部分是由ASCII码构成的帮助文件(*.doc),它包括指导用户的详细驱动程序帮助。
2 仪器驱动程序的操作
对用户来说,驱动程序完成一种或多种仪器功能,整个驱动程序库由多组程序有选择地构成。在Labwin的编程环境中选取仪器菜单,再从菜单中选取一个设备。这时将从屏幕中弹出一个功能面板,功能面板显示仪器的一些交互控制。函数调用自动生成的功能也随之加入整个应用程序。即使不提供功能面板,也能以手工方式进行驱动函数的调用。总地来说,设备驱动程序包括用以执行高级设备相关任务的功能函数。当用户把功能函数包含到程序中后,即使不了解设备的编程协议,也可以控制一个仪器正常运转。对它们的应用,可以在很大程度上减轻编程人员的负担。它们可以在软件开发中形成模块化,并大大提高软件的易用性和可维护性。
3 LabWindows/CVI开发驱动程序的优势
Labwin中设备的驱动程序是比传统概念中的驱动程序更高一层的概念。他们免去了编程人员频繁地同I/O端口打交道。它是放入用户应用程序的一种高层的软件功能。它不仅完全适用于目前各种标准的仪器设备,而且可对一大批老的仪器设备提供支持。
所有的Labwin应用的驱动程序,传递时在可能的情况下都伴有源码,并且很多都有完整的帮助文件。它们都是在Labwin的标准开发环境下开发的,用户可以根据具体情况改造自己的程序,使它们更加强大并对自己的应用程序有更大的弹性。
开发仪器驱动程序包括外部接口模块和内部设计模块。
3.1 外部接口模块
外部接口模块如图1所示。
功能主体:设备驱动的代码部分
程序员交互接口:图形化的编程助手,把交互控件状态转化为代码
程序员编程接口:调用各种函数
子程序接口:调用其它软件模块
3.2 内部设计模块
内部设计模块如图2所示。
功能主体:设备驱动的代码部分。包括初始化(包括结构复位、自检等)、设置函数(用一个软件程序集来实现相应功能。各种设备都有特定的设置函数。)、动作/状态函数(动作函数使仪器开始和停止测试,状态函数可获得仪器操作当前和即将出现的状态。)、数据函数(向仪器发送和接收数据)、终结函数(终结同仪器间的连接并释放系统资源)、应用程序函数(高级面向测试和功能函数)。
4 仪器驱动程序的设计
4.1 设计原则
在设计之前,必须进行驱动程序结构的设计,因为如果驱动程序的结构比较明了,会使程序员设计应用程序时更有条理。
其次,一定要把设计的驱动程序基于一个已设计好的核心驱动程序(即Labwin自带的驱动程序库)、或者是由一个核心驱动程序演化出来的驱动程序。
最后,以一个明确的步骤来编写你的仪器驱动程序(将在后面介绍)。
4.2 设计步骤
(1)命名这个驱动程序。
(2)定义这个驱动程序的功能和类。
(3)建立一个驱动程序的功能树。在Labwin中的功能树都以*.fp模式存储,并在引用时以层次化形式出现,并且在各分支功能上加帮助信息。
(4)对于程序中的每个函数:
——对于函数的参数定义包括变量类型、变量范围、错误代码等相关信息;
——在功能面板上实现新功能的创建,包括对功能面板和其中各个控件的帮助信息;
——为执行功能函数写代码;
——检验代码执行效果。
(5)为最终的设备源程序创建包含文件,包括函数定义和常量声明。
4.3 两个辅助工具介绍
(1)功能树的编辑器
用图3所示的是功能树编辑器,可以灵活地添加和删除各种函数,可从各个分支进入具体的函数定义功能面板编辑器。
图4所示的功能面板编辑器,可以控件的形式描述诸如函数参数、返回值、参考说明等函数的相关信息。随着各种控件的加入,相应的源代码也被实时地翻译在面板下方的文本框中。
4.4 自定义的数据类型
控件的使用方法相当简单,只需补充常说的可移植性问题,这一点同数据的定义是分不开的。Labwin对于驱动程序开发有自己专门的一套数据类型,它们可以精确地定义参数的类型和大小,而且它们具有很好的可移植性。各种定义如表1所示。
表1各种定义
4.5 函数定义的方法
驱动程序函数调用的返回值也与众不同,VISA/IO(Labwin中的虚拟设备接口)定义了一种非常有用的调用设备函数时使用的宏,如表2所示。
表2函数的定义
因为沿用了在Pascal语言中调用在DLL程序驱动的习惯,当用户在Labwin的环境调用用户定义函数时,把宏_VI_FUNC(表示任何用户函数)翻译成_pascal,而使用外部编译器编译时,则把宏解释成_far_pascal_export。同样在Labwin中,_VI_FAR(表示用户函数中任何的数组参数和输出变量)被翻译成空,而用其它编译程序时,被翻译成_far。
如下面这个函数 :
ViStatus _VI_FUNC tek2430a_read_waveform (ViSession instrSession,
ViReal64 _VI_FAR wvfm[],
ViReal64 _VI_FAR * xin,
ViReal64 _VI_FAR * trig_off);
在 LabWindows/CVI环境时,表示为:
ViStatus _pascal tek2430a_read_waveform (ViSession instrSession,
ViReal64 wvfm[],
ViReal64 * xin,
ViReal64 * trig_off);
而在其它编译环境下,表示为:
ViStatus _far _pascal _export tek2430a_read_waveform (ViSession instrSession,
ViReal64 _far wvfm[],
ViReal64 _far * xin,
ViReal64 _far * trig_off);
5 在BC3192测试程序中的应用实例
VXI的设备驱动程序包括以下几个主要功能。首先是分配设备的地址指针,这需要定义动态链接库的代码段和数据段为可移动和可删除,因为要用基指针指向每一个I/O动作,所以代码段和数据段是不定的;其次是VXI总线寄存器的写入和读取动作,这些操作需要我们使用刚得到的设备地址指针;再次是向缓存中读取和写入信息。另外,还有初始化,以及系统固定延迟时间等一系列功能。
在BC3192的测试程序中,结合Labwin自带的VXI总线的设备驱动程序,编写了一个简单的VXI驱动程序。它存于程序的根目录中,有4个支持文件,分别是vxirw.c、vxirw.dll、vxirw.h以及vxirw.lib。在我们的程序中,由于考虑到工作的效率,决定使用在VisualC++1.5的编译环境下,编译vxirw.c和vxirw.h程序,生成vxirw.dll及vxirw.lib的高效方法。这是由于Labwin使用一种LCC内建解释器对程序进行解释,其效率远不如直接使用动态链接库方便。用VC编译器编译的动态链接文件,可以在Labwin的函数中方便地进行调用。而且其效率同VC自身的调用不相上下。
如下面代码所示,正是使用了刚才所表示的函数调用方法。
void FAR PASCAL __export __loadds ReadReg(UINT La, UINT Offset, UINT FAR * Data)
/* 这 是 用 于 读 取 总 线 寄 存 器 的 函 数 。 * /
{
/* * Data=(UINT)(* (pPointer+ La* 32+ Offset/2)); * /
/* get the address pointer * /
GetPointer(La); /* 调用La全局变量取得寄存器地址*
/* read register * /
* Data=(UINT)(* (pPointer+ Offset/2)); / *把寄存器中的值通过偏移地址取出* /
/* free the selector * /
FreeSelector(wSelector);/*释放在取寄存器的值时所用到的字选择临时变量。 * /
}
程序的调用要熟悉大量硬件的特性,不属于软件总体设计之列,在此不再介绍。
6 结论
LabWindows这种以C语言为中心的编程方式有其优势,所带的C语言的功能比较灵活,而又便于开发一些大型的工程。它的类库的功能又可以开放地进行扩充,使系统的功能得到进一步增强。相对地,新型编程方式只能在固定的自带环境中运行,而且在表达复杂关系时,流程图的联系方式有很大的局限性。所以,Labwindows的编程方式在一段时间内将仍然拥有其地位。而今后的发展很可能是把两种编程方法进行集成,使我们在建立流程图后可以生成大部分程序代码,而细微的地方又可以进行C语言的调整。这样,我们的编程人员将拥有更方便的编程工具。
举报