📄 4.虚拟仪器驱动程序.txt
字号:
2、 仪器接口必须具有可扩展性:不仅要对现有的虚拟仪器实现这样的接口,而且
当有新的虚拟仪器出现时,要求整个平台同样能够在这样一个接口上实现对这种新
仪器的操作与控制。
3、 仪器接口控件必须能实现所有的驱动程序提供的函数,就是说驱动程序中的功
能在经过这样一个接口之后依然能全部实现。
4、 在能实现正确的函数调用同时,必须考虑函数调用的效率。
5、 在设计时应考虑程序容错性与健壮性等问题。
由上可知,要进行仪器接口控件的设计,首先必须从虚拟仪器驱动程序中获取相关
信息,可以有几种方案提供比较选择:
第一种方案是分析仪器驱动程序的头文件(.h文件),头文件中包括了所有的函数
原型与参数类型,为平台分析仪器操作函数提供了最基本的信息。但是,头文件并
不是一个标准规范的文件,它包括的代码顺序是无关的,中间又可以在任意位置嵌
入一些注释与宏定义,整个文件结构是文本描述性的,没有对函数信息进行一定格
式化的整理与封装,且信息量不大(没有帮助信息可以分析),因此,接口模块要
分析头文件中的有用信息,是事倍而功半的。
第二种方案是自定义一种文本描述性文件,将驱动程序中所需要的信息以一个纯文
本文件形式进行保存封装,这样接口模块对其分析是透明的,信息量的大小也完全
可以由文本描述的详细程度来确定。然而,这种想法在实现上也不容易,由于仪器
的种类千差万别,将仪器驱动程序的信息以一种文本文件进行记录描述,本身的工
作量就可想而知。并且虽然文本文件对于用户是比较直接简单,但对于整个系统来
说是结构松散,资源浪费,且文件定位复杂,编程工作量也较繁琐。
第三种方案即是利用功能面板文件,如上所述,功能面板文件是一个结构化定义的
文件,包括了仪器、函数类、函数、函数中的参数的所有描述信息,不仅有类型说
明,还有详细的各级帮助文本。整个功能面板文件结构有详细定义规范,因此,接
口模块的任务即是如何分析这个功能面板文件结构,将其中信息以可视化的形式表
示出来,并组合相应的驱动程序动态链接库文件,进行相应的函数调用。这种方法
的提出,兼顾了效率与扩展性,为接口模块的设计提供了理论基础。在本图形化平
台中虚拟仪器接口模块的设计中,即采用了这种接口方案。
在本章中,只给出了图形化平台的虚拟仪器接口模块的设计思想与实现方法,具体
的设计思路与实现步骤将在第七章图形化平台的设计中详细描述。而虚拟仪器功能
面板文件的设计,作为驱动程序设计的一部分,应结合仪器驱动程序的源代码设计
一起进行,在下一节中将进行进一步描述。
4.4 虚拟仪器驱动程序的设计
4.4.1 虚拟仪器驱动程序的设计原则
虚拟仪器驱动程序是虚拟仪器系统软件结构中重要一部分,结合实际开发经验,本
文列举了符合VPP规范要求的虚拟仪器驱动程序设计的几个原则:
1、 所有仪器函数的编写都基于I/O接口软件,在VPP系统中,一般基于VISA I/O接
口软件。
2、 所有仪器函数定义的数据类型均是VISA软件定义的数据类型。
3、 所有仪器函数必须包含一个返回状态值,它的类型是唯一的,为ViStatus。
4、 所有仪器函数名不能超过31个字符,在定义函数名之前,应带宏定义名
_VI_FUNC,在定义函数中数组类型参数与输出参数时,参数名前必须带宏定义名
_VI_FAR。所有仪器函数名的带有前缀PREFIX_,这个前缀一般即为仪器名,如HP公
司的信号发生器模块hpe1441仪器初始化函数名可定义为hpe1441_init()。
5、 尽量避免引出全局变量,避免声明大型数组结构,避免声明复杂的数据类型(
如类、结构、联合等),不采用键盘/屏幕标准输入/输出方式。
6、 仪器函数应避免包括高级的、复杂的数学分析与运算函数,而将此类复杂的运
算与分析工作交与上层应用程序来完成。
7、 仪器函数应具有较强的内聚力,尽量做到一个仪器函数完成一个独立的仪器功
能,实现有效的功能分配。
8、 仪器驱动程序中各函数之间尽量提高各自的独立性,减少彼此的耦合度。函数
之间必要的耦合采用数据耦合方式,而尽量避免采用功能耦合方式,从而有效地控
制仪器函数个数与规模。
4.4.2 虚拟仪器驱动程序的设计步骤
虚拟仪器驱动程序的设计必须遵循一定的设计原则,在实际的设计过程中,探寻出
一系列设计步骤,对于提高程序设计效率是事半功倍的。本节结合开发实例,提出
了虚拟仪器驱动程序的一般设计步骤,从而使驱动程序的设计有“法”可依。
第一步是应确定所研制的仪器模块类型,是属于VXI仪器、GPIB仪器还是串行接口
仪器。对于VXI仪器而言,需进一步确定是属于消息基器件、寄存器基器件还是存
储器基器件。如浙江大学数字技术及仪器研究所研制的高精度数据采集模块是基于
VXI总线的寄存器基器件,而GPIB2000数据采集仪属于基于GPIB总线的消息基器件
。
第二步是应确定仪器模块的应用目标及功能指标。与仪器硬件模块开发所关注的侧
重点不同的是,仪器硬件模块所关心的技术指标往往是性能指标,包括精度、灵敏
度、线性度、动态响应、使用环境温度范围以及可靠性指标等一系列静、动态指标
,而仪器驱动程序关心的指标更注重于仪器的功能指标。
以浙江大学数字技术及仪器研究所开发的可编程数字输入/输出模块为例,主要应
实现的功能包括:
1、 输入/输出端口可编程设置;
2、 可实现位、字节、字及长字多种数据格式操作;
3、 输入/输出数据、控制线及标志位极性可编程;
4、 可编程设置模块间通讯的握手协议与延迟时间;
5、 可完成数据块的读/写操作;
6、 可与外部文件进行数据存取操作;
7、 具有仪器自检功能;
8、 具有仪器复位功能;
9、 可进行仪器错误查询。
第三步是确定仪器驱动程序的函数组成结构,即设计功能面板文件的树型结构,从
上到下由仪器结点(根结点)、类结点(枝结点)与函数结点(叶结点)层次化构
成。功能面板文件树型结构的确定,也就确定了驱动程序所需要包括的所有功能函
数,是仪器驱动程序内部设计模型的表示。
以浙江大学数字技术及仪器研究所自主开发的VXI寄存器基器件可编程数字输入/输
出模块为例,功能面板文件基本树型结构如图4.9所示。
根据功能面板文件树型结构,将仪器驱动程序所需包含的功能函数分为以下几类,
斜体字分别表示仪器与类别点,非斜体字表示函数结点,分别说明如下(文中以斜
体表示类,以正体表示函数):
图4.9 可编程数字输入/输出模块功能面板文件基本树型结构图
1. Initialize:初始化函数,建立驱动程序与仪器的通信联系。
2. Configure:配置类,设置仪器通讯协议,包括:
2.1 Handshake:设置输入/输出协议中的握手模式与延迟时间。
2.2 Handshake Query:查询输入/输出协议中的握手模式与延迟时间。
2.3 Polarity:设置输入/输出协议中的极性。
2.4 Polarity Query:查询输入/输出协议中的极性。
2.5 Trace:块操作配置类,进行数据块特性设置,包括:
2.5.1 Define Trace:定义数据块在内存中对应的存储单元。
2.5.2 Define Trace Query:查询数据块在内存中对应的存储单元。
2.5.3 Trace Data:特定数据块的输入/输出。
2.5.4 Catalog Trace:列出所定义的所有数据块单元。
2.5.5 Delete Trace:删除特定的数据块单元。
2.5.6 Delete All Traces:删除所有数据块单元。
3、Application Functions:应用类,进行数据输入/输出操作,包括:
3.1 Input:输入类,包括:
3.1.1 Input Byte:8位数据端口输入。
3.1.2 Input Word:2个独立的8位数据端口输入。
3.1.3 Input LWord:4个独立的8位数据端口输入。
3.1.4 Input LW48:6个独立的8位数据端口输入。
3.1.5 Input LW96:12个独立的8位数据端口输入。
3.1.6 Input Trace File:数据块由文件输入。
3.2 Output:输出类,包括:
3.2.1 Output Byte: 8位数据端口输出。
3.2.2 Output Word:2个独立的8位数据端口输出。
3.2.3 Output LWord:4个独立的8位数据端口输出。
3.2.4 Output LW48:6个独立的8位数据端口输出。
3.2.5 Output LW96:12个独立的8位数据端口输出。
3.2.6 Output Trace File:数据块向文件输出。
4、Utitlity:实用函数类,包括仪器驱动程序内部设计模型中定义的通用函数。
4.1 Reset:仪器复位到缺省状态。在本模块中,缺省状态为所有数据端口置为输
入模块,没有设置握手模式,握手延迟时间设为2微秒,所有极性均置为正极性状
态,控制线置为无效态。
4.2 Self-test:进行仪器自检。
4.3 Error Query:进行仪器错误查询。
4.4 Error Message:将错误代码转换为错误信息。
4.5 Revision Query:仪器驱动程序与固件版本查询。
4.6 Set Timeout:设置超时值。
4.7 Query Timeout:查询超时值。
4.8 Device Clear:器件清除。
5、 Close:关闭函数,终止软件与仪器的通讯联系,并释放系统资源。
第四步是仪器驱动程序的实质部分,即源代码的编写(包括.c与.h文件)。设计人
员从头到尾地编写,往往工作量大且容易出错。为了提高驱动程序的编写效率与正
确性,本文分析讨论了一些现有的设计方法,并提出一些新设计思路与实现,从而
减轻设计人员编程负担。
1、 核心模块扩充法:所谓仪器驱动程序的核心模块,实质是将同类仪器中功能函
数的最大公约集封装到一起,编写成核心模块的源代码。由于核心模块中包括的功
能函数是最大公约集,具体的仪器驱动程序都包括了这些功能函数,因此,在编写
这些仪器驱动程序时,这些通用的功能函数无需重写,直接拷贝进来即可,唯一要
做的工作是将核心模块中的前缀PREFIX替换成特定仪器名前缀。这种方法主要是省
去了一些通用功能函数的重复编写的工作量,同时给出了其它功能函数的编写格式
。NI公司推出了VXI器件、GPIB器件、RS232串行接口仪器的核心模块程序,但源代
码中包含了许多NI公司产品特有的参数类型与属性,兼容性不好。为此,在本课题
研究中,重新编写VXI器件、GPIB器件、RS232串行接口仪器的核心程序,分别为
core_vxi.c(core_vxi.h)、core_gpib.c(core_gpib.h)、core_rs232.c(
core_rs232.h)文件,其中由于串行接口仪器的功能函数比较简要,在一些基本应
用场合,只需经过前缀替换后,可以直接生成了基本的仪器驱动程序,被上层应用
程序调用。需要说明的是,由于VXI寄存器基器件不直接支持SCPI命令格式,因此
VXI器件的核心模块只适用于扩充VXI消息基器件而不适用于寄存器基器件。下面列
出的是VXI器件核心模块的头文件core_vxi.h。
/* Copyright (C) 1995 Test & Measurement Institute of Zhejiang
University */
/* VXIplug&play Instrument Driver for the VXI module*/
#ifndef PREFIX_INCLUDE
#define PREFIX_INCLUDE
#include "vpptype.h"
#if defined(__cplusplus) || defined(__cplusplus__)
extern "C" {
#endif
/****** Returned error status values *****/
#define VI_ERROR_FILE_OPEN (_VI_ERROR+0x3FFC0001L) /*
0xBFFC0001 */
#define VI_ERROR_FILE_WRITE (_VI_ERROR+0x3FFC0002L) /*
0xBFFC0002 */
#define VI_ERROR_INTERPRETING_RESPONSE (_VI_ERROR+0x3FFC0003L) /*
0xBFFC0003 */
/* Common Error numbers start at BFFC0D00 */
#define prefix_INSTR_ERROR_NOT_VXI (_VI_ERROR+0x3FFC0D00L) /*
0xBFFC0D00 */
/* D01 unused*/
#define prefix_INSTR_ERROR_NULL_PTR (_VI_ERROR+0x3FFC0D02L) /*
0xBFFC0D02 */
#define prefix_INSTR_ERROR_RESET_FAILED (_VI_ERROR+0x3FFC0D03L) /*
0xBFFC0D03 */
#define prefix_INSTR_ERROR_UNEXPECTED (_VI_ERROR+0x3FFC0D04L) /*
0xBFFC0D04 */
#define prefix_INSTR_ERROR_INV_SESSION (_VI_ERROR+0x3FFC0D05L) /*
0xBFFC0D05 */
#define prefix_INSTR_ERROR_LOOKUP (_VI_ERROR+0x3FFC0D06L) /*
0xBFFC0D06 */
#define prefix_INSTR_ERROR_DETECTED (_VI_ERROR+0x3FFC0D07L) /*
0xBFFC0D07 */
/* Parameter errors not in VPP 3.4 */
#define prefix_INSTR_ERROR_PARAMETER9 (_VI_ERROR+0x3FFC0D20L)/*
0xBFFC0D20 */
#define prefix_INSTR_ERROR_PARAMETER10 (_VI_ERROR+0x3FFC0D21L)/*
0xBFFC0D21 */
#define prefix_INSTR_ERROR_PARAMETER11 (_VI_ERROR+0x3FFC0D22L)/*
0xBFFC0D22 */
#define prefix_INSTR_ERROR_PARAMETER12 (_VI_ERROR+0x3FFC0D23L)/*
0xBFFC0D23 */
#define prefix_INSTR_ERROR_PARAMETER13 (_VI_ERROR+0x3FFC0D24L)/*
0xBFFC0D24 */
#define prefix_INSTR_ERROR_PARAMETER14 (_VI_ERROR+0x3FFC0D25L)/*
0xBFFC0D25 */
#define prefix_INSTR_ERROR_PARAMETER15 (_VI_ERROR+0x3FFC0D26L)/*
0xBFFC0D26 */
#define prefix_INSTR_ERROR_PARAMETER16 (_VI_ERROR+0x3FFC0D27L)/*
0xBFFC0D27 */
#define prefix_INSTR_ERROR_PARAMETER17 (_VI_ERROR+0x3FFC0D28L)/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -